Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Unified Diff: src/x64/codegen-x64.cc

Issue 3050008: Add EmitNamedStore and CallStoreIC(name, is_contextual) to x64 platform. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/virtual-frame-x64.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/codegen-x64.cc
===================================================================
--- src/x64/codegen-x64.cc (revision 5107)
+++ src/x64/codegen-x64.cc (working copy)
@@ -5006,16 +5006,150 @@
}
+void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
+#ifdef DEBUG
+ int original_height = frame()->height();
+#endif
+ Comment cmnt(masm(), "[ Named Property Assignment");
+ Variable* var = node->target()->AsVariableProxy()->AsVariable();
+ Property* prop = node->target()->AsProperty();
+ ASSERT(var == NULL || (prop == NULL && var->is_global()));
+
+ // 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) {
+ name = var->name();
+ } else {
+ Literal* lit = prop->key()->AsLiteral();
+ ASSERT_NOT_NULL(lit);
+ name = Handle<String>::cast(lit->handle());
+ // 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());
+ }
+
+ // 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);
+ if (is_trivial_receiver) {
+ frame()->Push(prop->obj());
+ } else {
+ 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() && !is_trivial_receiver) {
+ 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) {
+ // The LoadIC stub expects the object in rax.
+ // Freeing rax causes the code generator to load the global into it.
+ frame_->Spill(rax);
+ LoadGlobal();
+ } else {
+ frame()->Dup();
+ }
+ Result value = EmitNamedLoad(name, var != NULL);
+ frame()->Push(&value);
+ Load(node->value());
+
+ bool overwrite_value =
+ (node->value()->AsBinaryOperation() != NULL &&
+ node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
+ // Construct the implicit binary operation.
+ BinaryOperation expr(node, node->binary_op(), node->target(),
+ node->value());
+ 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());
+ if (is_trivial_receiver) {
+ Result value = frame()->Pop();
+ frame()->Push(prop->obj());
+ frame()->Push(&value);
+ }
+ CodeForSourcePosition(node->position());
+ bool is_contextual = (var != NULL);
+ 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.
+ 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);
+ }
+
+ // Stack layout:
+ // [tos] : result
+
+ ASSERT_EQ(frame()->height(), original_height + 1);
+}
+
+
void CodeGenerator::VisitAssignment(Assignment* node) {
#ifdef DEBUG
int original_height = frame()->height();
#endif
Variable* var = node->target()->AsVariableProxy()->AsVariable();
- // Property* prop = node->target()->AsProperty();
+ Property* prop = node->target()->AsProperty();
if (var != NULL && !var->is_global()) {
EmitSlotAssignment(node);
+ } else if ((prop != NULL && prop->key()->IsPropertyName()) ||
+ (var != NULL && var->is_global())) {
+ // Properties whose keys are property names and global variables are
+ // treated as named property references. We do not need to consider
+ // global 'this' because it is not a valid left-hand side.
+ EmitNamedPropertyAssignment(node);
+
} else {
Comment cmnt(masm_, "[ Assignment");
@@ -7847,6 +7981,22 @@
}
+Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
+#ifdef DEBUG
+ int expected_height = frame()->height() - (is_contextual ? 1 : 2);
+#endif
+
+ Result result = frame()->CallStoreIC(name, is_contextual);
+ // A test eax instruction following the call signals that the inobject
+ // property case was inlined. Ensure that there is not a test eax
+ // instruction here.
+ __ nop();
+
+ ASSERT_EQ(expected_height, frame()->height());
+ return result;
+}
+
+
Result CodeGenerator::EmitKeyedLoad() {
#ifdef DEBUG
int original_height = frame()->height();
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/virtual-frame-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698