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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 2878042: Add EmitSlotAssignment 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 4947 matching lines...) Expand 10 before | Expand all | Expand 10 after
4958 // assign the exception value to the catch variable. 4958 // assign the exception value to the catch variable.
4959 Comment cmnt(masm_, "[ CatchExtensionObject"); 4959 Comment cmnt(masm_, "[ CatchExtensionObject");
4960 Load(node->key()); 4960 Load(node->key());
4961 Load(node->value()); 4961 Load(node->value());
4962 Result result = 4962 Result result =
4963 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2); 4963 frame_->CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
4964 frame_->Push(&result); 4964 frame_->Push(&result);
4965 } 4965 }
4966 4966
4967 4967
4968 void CodeGenerator::EmitSlotAssignment(Assignment* node) {
4969 #ifdef DEBUG
4970 int original_height = frame()->height();
4971 #endif
4972 Comment cmnt(masm(), "[ Variable Assignment");
4973 Variable* var = node->target()->AsVariableProxy()->AsVariable();
4974 ASSERT(var != NULL);
4975 Slot* slot = var->slot();
4976 ASSERT(slot != NULL);
4977
4978 // Evaluate the right-hand side.
4979 if (node->is_compound()) {
4980 // For a compound assignment the right-hand side is a binary operation
4981 // between the current property value and the actual right-hand side.
4982 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
4983 Load(node->value());
4984
4985 // Perform the binary operation.
4986 bool overwrite_value =
4987 (node->value()->AsBinaryOperation() != NULL &&
4988 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
4989 // Construct the implicit binary operation.
4990 BinaryOperation expr(node, node->binary_op(), node->target(),
4991 node->value());
4992 GenericBinaryOperation(&expr,
4993 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
4994 } else {
4995 // For non-compound assignment just load the right-hand side.
4996 Load(node->value());
4997 }
4998
4999 // Perform the assignment.
5000 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) {
5001 CodeForSourcePosition(node->position());
5002 StoreToSlot(slot,
5003 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT);
5004 }
5005 ASSERT(frame()->height() == original_height + 1);
5006 }
5007
5008
4968 void CodeGenerator::VisitAssignment(Assignment* node) { 5009 void CodeGenerator::VisitAssignment(Assignment* node) {
4969 Comment cmnt(masm_, "[ Assignment"); 5010 #ifdef DEBUG
5011 int original_height = frame()->height();
5012 #endif
5013 Variable* var = node->target()->AsVariableProxy()->AsVariable();
5014 // Property* prop = node->target()->AsProperty();
4970 5015
4971 { Reference target(this, node->target(), node->is_compound()); 5016 if (var != NULL && !var->is_global()) {
4972 if (target.is_illegal()) { 5017 EmitSlotAssignment(node);
4973 // Fool the virtual frame into thinking that we left the assignment's
4974 // value on the frame.
4975 frame_->Push(Smi::FromInt(0));
4976 return;
4977 }
4978 Variable* var = node->target()->AsVariableProxy()->AsVariable();
4979 5018
4980 if (node->starts_initialization_block()) { 5019 } else {
4981 ASSERT(target.type() == Reference::NAMED || 5020 Comment cmnt(masm_, "[ Assignment");
4982 target.type() == Reference::KEYED);
4983 // Change to slow case in the beginning of an initialization
4984 // block to avoid the quadratic behavior of repeatedly adding
4985 // fast properties.
4986 5021
4987 // The receiver is the argument to the runtime call. It is the 5022 { Reference target(this, node->target(), node->is_compound());
4988 // first value pushed when the reference was loaded to the 5023 if (target.is_illegal()) {
4989 // frame. 5024 // Fool the virtual frame into thinking that we left the assignment's
4990 frame_->PushElementAt(target.size() - 1); 5025 // value on the frame.
4991 Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1); 5026 frame_->Push(Smi::FromInt(0));
4992 } 5027 return;
4993 if (node->ends_initialization_block()) {
4994 // Add an extra copy of the receiver to the frame, so that it can be
4995 // converted back to fast case after the assignment.
4996 ASSERT(target.type() == Reference::NAMED ||
4997 target.type() == Reference::KEYED);
4998 if (target.type() == Reference::NAMED) {
4999 frame_->Dup();
5000 // Dup target receiver on stack.
5001 } else {
5002 ASSERT(target.type() == Reference::KEYED);
5003 Result temp = frame_->Pop();
5004 frame_->Dup();
5005 frame_->Push(&temp);
5006 } 5028 }
5007 }
5008 if (node->op() == Token::ASSIGN ||
5009 node->op() == Token::INIT_VAR ||
5010 node->op() == Token::INIT_CONST) {
5011 Load(node->value());
5012 5029
5013 } else { // Assignment is a compound assignment. 5030 if (node->starts_initialization_block()) {
5014 Literal* literal = node->value()->AsLiteral(); 5031 ASSERT(target.type() == Reference::NAMED ||
5015 bool overwrite_value = 5032 target.type() == Reference::KEYED);
5016 (node->value()->AsBinaryOperation() != NULL && 5033 // Change to slow case in the beginning of an initialization
5017 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 5034 // block to avoid the quadratic behavior of repeatedly adding
5018 Variable* right_var = node->value()->AsVariableProxy()->AsVariable(); 5035 // fast properties.
5019 // There are two cases where the target is not read in the right hand
5020 // side, that are easy to test for: the right hand side is a literal,
5021 // or the right hand side is a different variable. TakeValue invalidates
5022 // the target, with an implicit promise that it will be written to again
5023 // before it is read.
5024 if (literal != NULL || (right_var != NULL && right_var != var)) {
5025 target.TakeValue();
5026 } else {
5027 target.GetValue();
5028 }
5029 Load(node->value());
5030 BinaryOperation expr(node, node->binary_op(), node->target(),
5031 node->value());
5032 GenericBinaryOperation(&expr,
5033 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
5034 }
5035 5036
5036 if (var != NULL && 5037 // The receiver is the argument to the runtime call. It is the
5037 var->mode() == Variable::CONST && 5038 // first value pushed when the reference was loaded to the
5038 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { 5039 // frame.
5039 // Assignment ignored - leave the value on the stack. 5040 frame_->PushElementAt(target.size() - 1);
5040 UnloadReference(&target); 5041 Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1);
5041 } else {
5042 CodeForSourcePosition(node->position());
5043 if (node->op() == Token::INIT_CONST) {
5044 // Dynamic constant initializations must use the function context
5045 // and initialize the actual constant declared. Dynamic variable
5046 // initializations are simply assignments and use SetValue.
5047 target.SetValue(CONST_INIT);
5048 } else {
5049 target.SetValue(NOT_CONST_INIT);
5050 } 5042 }
5051 if (node->ends_initialization_block()) { 5043 if (node->ends_initialization_block()) {
5052 ASSERT(target.type() == Reference::UNLOADED); 5044 // Add an extra copy of the receiver to the frame, so that it can be
5053 // End of initialization block. Revert to fast case. The 5045 // converted back to fast case after the assignment.
5054 // argument to the runtime call is the extra copy of the receiver, 5046 ASSERT(target.type() == Reference::NAMED ||
5055 // which is below the value of the assignment. 5047 target.type() == Reference::KEYED);
5056 // Swap the receiver and the value of the assignment expression. 5048 if (target.type() == Reference::NAMED) {
5057 Result lhs = frame_->Pop(); 5049 frame_->Dup();
5058 Result receiver = frame_->Pop(); 5050 // Dup target receiver on stack.
5059 frame_->Push(&lhs); 5051 } else {
5060 frame_->Push(&receiver); 5052 ASSERT(target.type() == Reference::KEYED);
5061 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); 5053 Result temp = frame_->Pop();
5054 frame_->Dup();
5055 frame_->Push(&temp);
5056 }
5057 }
5058 if (node->op() == Token::ASSIGN ||
5059 node->op() == Token::INIT_VAR ||
5060 node->op() == Token::INIT_CONST) {
5061 Load(node->value());
5062
5063 } else { // Assignment is a compound assignment.
5064 Literal* literal = node->value()->AsLiteral();
5065 bool overwrite_value =
5066 (node->value()->AsBinaryOperation() != NULL &&
5067 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
5068 Variable* right_var = node->value()->AsVariableProxy()->AsVariable();
5069 // There are two cases where the target is not read in the right hand
5070 // side, that are easy to test for: the right hand side is a literal,
5071 // or the right hand side is a different variable. TakeValue
5072 // invalidates the target, with an implicit promise that it will be
5073 // written to again
5074 // before it is read.
5075 if (literal != NULL || (right_var != NULL && right_var != var)) {
5076 target.TakeValue();
5077 } else {
5078 target.GetValue();
5079 }
5080 Load(node->value());
5081 BinaryOperation expr(node, node->binary_op(), node->target(),
5082 node->value());
5083 GenericBinaryOperation(
5084 &expr, overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
5085 }
5086 if (var != NULL &&
5087 var->mode() == Variable::CONST &&
5088 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
5089 // Assignment ignored - leave the value on the stack.
5090 UnloadReference(&target);
5091 } else {
5092 CodeForSourcePosition(node->position());
5093 if (node->op() == Token::INIT_CONST) {
5094 // Dynamic constant initializations must use the function context
5095 // and initialize the actual constant declared. Dynamic variable
5096 // initializations are simply assignments and use SetValue.
5097 target.SetValue(CONST_INIT);
5098 } else {
5099 target.SetValue(NOT_CONST_INIT);
5100 }
5101 if (node->ends_initialization_block()) {
5102 ASSERT(target.type() == Reference::UNLOADED);
5103 // End of initialization block. Revert to fast case. The
5104 // argument to the runtime call is the extra copy of the receiver,
5105 // which is below the value of the assignment.
5106 // Swap the receiver and the value of the assignment expression.
5107 Result lhs = frame_->Pop();
5108 Result receiver = frame_->Pop();
5109 frame_->Push(&lhs);
5110 frame_->Push(&receiver);
5111 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
5112 }
5062 } 5113 }
5063 } 5114 }
5064 } 5115 }
5116 // Stack layout:
5117 // [tos] : result
5118
5119 ASSERT(frame()->height() == original_height + 1);
5065 } 5120 }
5066 5121
5067 5122
5068 void CodeGenerator::VisitThrow(Throw* node) { 5123 void CodeGenerator::VisitThrow(Throw* node) {
5069 Comment cmnt(masm_, "[ Throw"); 5124 Comment cmnt(masm_, "[ Throw");
5070 Load(node->exception()); 5125 Load(node->exception());
5071 Result result = frame_->CallRuntime(Runtime::kThrow, 1); 5126 Result result = frame_->CallRuntime(Runtime::kThrow, 1);
5072 frame_->Push(&result); 5127 frame_->Push(&result);
5073 } 5128 }
5074 5129
(...skipping 7040 matching lines...) Expand 10 before | Expand all | Expand 10 after
12115 #undef __ 12170 #undef __
12116 12171
12117 void RecordWriteStub::Generate(MacroAssembler* masm) { 12172 void RecordWriteStub::Generate(MacroAssembler* masm) {
12118 masm->RecordWriteHelper(object_, addr_, scratch_); 12173 masm->RecordWriteHelper(object_, addr_, scratch_);
12119 masm->ret(0); 12174 masm->ret(0);
12120 } 12175 }
12121 12176
12122 } } // namespace v8::internal 12177 } } // namespace v8::internal
12123 12178
12124 #endif // V8_TARGET_ARCH_X64 12179 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698