From 5a3ea1c83e70d0918403bfaa7077fe224162d4db Mon Sep 17 00:00:00 2001 From: "sgjesse@chromium.org" Date: Wed, 5 May 2010 06:57:41 +0000 Subject: [PATCH] Add some comments to the ia32 code generator Review URL: http://codereview.chromium.org/1918002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4586 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/codegen-arm.cc | 2 +- src/ia32/codegen-ia32.cc | 75 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 8f9fa30..30860a1 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -3333,7 +3333,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { // Change to slow case in the beginning of an initialization block to // avoid the quadratic behavior of repeatedly adding fast properties. if (node->starts_initialization_block()) { - // Initialization block consists of assignments on the form expr.x = ..., so + // Initialization block consists of assignments of the form expr.x = ..., so // this will never be an assignment to a variable, so there must be a // receiver object. ASSERT_EQ(NULL, var); diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 23e7c6e..83060c1 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -5369,10 +5369,13 @@ void CodeGenerator::EmitSlotAssignment(Assignment* node) { // Evaluate the right-hand side. if (node->is_compound()) { + // For a compound assignment the right-hand side is a binary operation + // between the current property value and the actual right-hand side. Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); frame()->Push(&result); Load(node->value()); + // Perform the binary operation. bool overwrite_value = (node->value()->AsBinaryOperation() != NULL && node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); @@ -5382,6 +5385,7 @@ void CodeGenerator::EmitSlotAssignment(Assignment* node) { GenericBinaryOperation(&expr, overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); } else { + // For non-compound assignment just load the right-hand side. Load(node->value()); } @@ -5404,7 +5408,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 if necessary. + // Initialize name and evaluate the receiver sub-expression if necessary. If + // the receiver is trivial it is not placed on the stack at this point, but + // loaded whenever actually needed. Handle name; bool is_trivial_receiver = false; if (var != NULL) { @@ -5418,10 +5424,13 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { if (!is_trivial_receiver) Load(prop->obj()); } + // Change to slow case in the beginning of an initialization block to + // avoid the quadratic behavior of repeatedly adding fast properties. if (node->starts_initialization_block()) { + // Initialization block consists of assignments of the form expr.x = ..., so + // this will never be an assignment to a variable, so there must be a + // receiver object. ASSERT_EQ(NULL, var); - // Change to slow case in the beginning of an initialization block to - // avoid the quadratic behavior of repeatedly adding fast properties. if (is_trivial_receiver) { frame()->Push(prop->obj()); } else { @@ -5430,14 +5439,21 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { Result ignored = frame()->CallRuntime(Runtime::kToSlowProperties, 1); } + // Change to fast case at the end of an initialization block. To prepare for + // that add an extra copy of the receiver to the frame, so that it can be + // converted back to fast case after the assignment. 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(); } + // Stack layout: + // [tos] : receiver (only materialized if non-trivial) + // [tos+1] : receiver if at the end of an initialization block + // Evaluate the right-hand side. if (node->is_compound()) { + // For a compound assignment the right-hand side is a binary operation + // between the current property value and the actual right-hand side. if (is_trivial_receiver) { frame()->Push(prop->obj()); } else if (var != NULL) { @@ -5461,9 +5477,15 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { GenericBinaryOperation(&expr, overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); } else { + // For non-compound assignment just load the right-hand side. Load(node->value()); } + // Stack layout: + // [tos] : value + // [tos+1] : receiver (only materialized if non-trivial) + // [tos+2] : receiver if at the end of an initialization block + // Perform the assignment. It is safe to ignore constants here. ASSERT(var == NULL || var->mode() != Variable::CONST); ASSERT_NE(Token::INIT_CONST, node->op()); @@ -5477,6 +5499,10 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { Result answer = EmitNamedStore(name, is_contextual); frame()->Push(&answer); + // Stack layout: + // [tos] : result + // [tos+1] : receiver if at the end of an initialization block + if (node->ends_initialization_block()) { ASSERT_EQ(NULL, var); // The argument to the runtime call is the receiver. @@ -5493,6 +5519,9 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); } + // Stack layout: + // [tos] : result + ASSERT_EQ(frame()->height(), original_height + 1); } @@ -5501,38 +5530,47 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) { #ifdef DEBUG int original_height = frame()->height(); #endif - Comment cmnt(masm_, "[ Named Property Assignment"); + Comment cmnt(masm_, "[ Keyed Property Assignment"); Property* prop = node->target()->AsProperty(); ASSERT_NOT_NULL(prop); // Evaluate the receiver subexpression. Load(prop->obj()); + // Change to slow case in the beginning of an initialization block to + // avoid the quadratic behavior of repeatedly adding fast properties. 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(); Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1); } + // Change to fast case at the end of an initialization block. To prepare for + // that add an extra copy of the receiver to the frame, so that it can be + // converted back to fast case after the assignment. if (node->ends_initialization_block()) { - // 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(); } // Evaluate the key subexpression. Load(prop->key()); + // Stack layout: + // [tos] : key + // [tos+1] : receiver + // [tos+2] : receiver if at the end of an initialization block + // Evaluate the right-hand side. if (node->is_compound()) { - // Duplicate receiver and key. + // For a compound assignment the right-hand side is a binary operation + // between the current property value and the actual right-hand side. + // Duplicate receiver and key for loading the current property value. frame()->PushElementAt(1); frame()->PushElementAt(1); Result value = EmitKeyedLoad(); frame()->Push(&value); Load(node->value()); + // Perform the binary operation. bool overwrite_value = (node->value()->AsBinaryOperation() != NULL && node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); @@ -5541,15 +5579,27 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) { GenericBinaryOperation(&expr, overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); } else { + // For non-compound assignment just load the right-hand side. Load(node->value()); } + // Stack layout: + // [tos] : value + // [tos+1] : key + // [tos+2] : receiver + // [tos+3] : receiver if at the end of an initialization block + // Perform the assignment. It is safe to ignore constants here. ASSERT(node->op() != Token::INIT_CONST); CodeForSourcePosition(node->position()); Result answer = EmitKeyedStore(prop->key()->type()); frame()->Push(&answer); + // Stack layout: + // [tos] : result + // [tos+1] : receiver if at the end of an initialization block + + // Change to fast case at the end of an initialization block. 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 @@ -5561,6 +5611,9 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) { Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); } + // Stack layout: + // [tos] : result + ASSERT(frame()->height() == original_height + 1); } -- 2.7.4