Revision: 4586
Author: [email protected]
Date: Tue May 4 23:57:41 2010
Log: Add some comments to the ia32 code generator
Review URL: http://codereview.chromium.org/1918002
http://code.google.com/p/v8/source/detail?r=4586
Modified:
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Tue May 4 23:50:15 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Tue May 4 23:57:41 2010
@@ -3333,7 +3333,7 @@
// 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);
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue May 4 07:49:50
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue May 4 23:57:41
2010
@@ -5369,10 +5369,13 @@
// 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 @@
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 @@
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<String> name;
bool is_trivial_receiver = false;
if (var != NULL) {
@@ -5418,10 +5424,13 @@
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 @@
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,8 +5477,14 @@
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);
@@ -5477,6 +5499,10 @@
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.
@@ -5492,6 +5518,9 @@
}
Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
}
+
+ // Stack layout:
+ // [tos] : result
ASSERT_EQ(frame()->height(), original_height + 1);
}
@@ -5501,38 +5530,47 @@
#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,8 +5579,15 @@
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);
@@ -5550,6 +5595,11 @@
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
@@ -5560,6 +5610,9 @@
frame()->Push(&receiver);
Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
}
+
+ // Stack layout:
+ // [tos] : result
ASSERT(frame()->height() == original_height + 1);
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev