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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/virtual-frame-x64.h » ('j') | 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 4988 matching lines...) Expand 10 before | Expand all | Expand 10 after
4999 // Perform the assignment. 4999 // Perform the assignment.
5000 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { 5000 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) {
5001 CodeForSourcePosition(node->position()); 5001 CodeForSourcePosition(node->position());
5002 StoreToSlot(slot, 5002 StoreToSlot(slot,
5003 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT); 5003 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT);
5004 } 5004 }
5005 ASSERT(frame()->height() == original_height + 1); 5005 ASSERT(frame()->height() == original_height + 1);
5006 } 5006 }
5007 5007
5008 5008
5009 void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
5010 #ifdef DEBUG
5011 int original_height = frame()->height();
5012 #endif
5013 Comment cmnt(masm(), "[ Named Property Assignment");
5014 Variable* var = node->target()->AsVariableProxy()->AsVariable();
5015 Property* prop = node->target()->AsProperty();
5016 ASSERT(var == NULL || (prop == NULL && var->is_global()));
5017
5018 // Initialize name and evaluate the receiver sub-expression if necessary. If
5019 // the receiver is trivial it is not placed on the stack at this point, but
5020 // loaded whenever actually needed.
5021 Handle<String> name;
5022 bool is_trivial_receiver = false;
5023 if (var != NULL) {
5024 name = var->name();
5025 } else {
5026 Literal* lit = prop->key()->AsLiteral();
5027 ASSERT_NOT_NULL(lit);
5028 name = Handle<String>::cast(lit->handle());
5029 // Do not materialize the receiver on the frame if it is trivial.
5030 is_trivial_receiver = prop->obj()->IsTrivial();
5031 if (!is_trivial_receiver) Load(prop->obj());
5032 }
5033
5034 // Change to slow case in the beginning of an initialization block to
5035 // avoid the quadratic behavior of repeatedly adding fast properties.
5036 if (node->starts_initialization_block()) {
5037 // Initialization block consists of assignments of the form expr.x = ..., so
5038 // this will never be an assignment to a variable, so there must be a
5039 // receiver object.
5040 ASSERT_EQ(NULL, var);
5041 if (is_trivial_receiver) {
5042 frame()->Push(prop->obj());
5043 } else {
5044 frame()->Dup();
5045 }
5046 Result ignored = frame()->CallRuntime(Runtime::kToSlowProperties, 1);
5047 }
5048
5049 // Change to fast case at the end of an initialization block. To prepare for
5050 // that add an extra copy of the receiver to the frame, so that it can be
5051 // converted back to fast case after the assignment.
5052 if (node->ends_initialization_block() && !is_trivial_receiver) {
5053 frame()->Dup();
5054 }
5055
5056 // Stack layout:
5057 // [tos] : receiver (only materialized if non-trivial)
5058 // [tos+1] : receiver if at the end of an initialization block
5059
5060 // Evaluate the right-hand side.
5061 if (node->is_compound()) {
5062 // For a compound assignment the right-hand side is a binary operation
5063 // between the current property value and the actual right-hand side.
5064 if (is_trivial_receiver) {
5065 frame()->Push(prop->obj());
5066 } else if (var != NULL) {
5067 // The LoadIC stub expects the object in rax.
5068 // Freeing rax causes the code generator to load the global into it.
5069 frame_->Spill(rax);
5070 LoadGlobal();
5071 } else {
5072 frame()->Dup();
5073 }
5074 Result value = EmitNamedLoad(name, var != NULL);
5075 frame()->Push(&value);
5076 Load(node->value());
5077
5078 bool overwrite_value =
5079 (node->value()->AsBinaryOperation() != NULL &&
5080 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
5081 // Construct the implicit binary operation.
5082 BinaryOperation expr(node, node->binary_op(), node->target(),
5083 node->value());
5084 GenericBinaryOperation(&expr,
5085 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
5086 } else {
5087 // For non-compound assignment just load the right-hand side.
5088 Load(node->value());
5089 }
5090
5091 // Stack layout:
5092 // [tos] : value
5093 // [tos+1] : receiver (only materialized if non-trivial)
5094 // [tos+2] : receiver if at the end of an initialization block
5095
5096 // Perform the assignment. It is safe to ignore constants here.
5097 ASSERT(var == NULL || var->mode() != Variable::CONST);
5098 ASSERT_NE(Token::INIT_CONST, node->op());
5099 if (is_trivial_receiver) {
5100 Result value = frame()->Pop();
5101 frame()->Push(prop->obj());
5102 frame()->Push(&value);
5103 }
5104 CodeForSourcePosition(node->position());
5105 bool is_contextual = (var != NULL);
5106 Result answer = EmitNamedStore(name, is_contextual);
5107 frame()->Push(&answer);
5108
5109 // Stack layout:
5110 // [tos] : result
5111 // [tos+1] : receiver if at the end of an initialization block
5112
5113 if (node->ends_initialization_block()) {
5114 ASSERT_EQ(NULL, var);
5115 // The argument to the runtime call is the receiver.
5116 if (is_trivial_receiver) {
5117 frame()->Push(prop->obj());
5118 } else {
5119 // A copy of the receiver is below the value of the assignment. Swap
5120 // the receiver and the value of the assignment expression.
5121 Result result = frame()->Pop();
5122 Result receiver = frame()->Pop();
5123 frame()->Push(&result);
5124 frame()->Push(&receiver);
5125 }
5126 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
5127 }
5128
5129 // Stack layout:
5130 // [tos] : result
5131
5132 ASSERT_EQ(frame()->height(), original_height + 1);
5133 }
5134
5135
5009 void CodeGenerator::VisitAssignment(Assignment* node) { 5136 void CodeGenerator::VisitAssignment(Assignment* node) {
5010 #ifdef DEBUG 5137 #ifdef DEBUG
5011 int original_height = frame()->height(); 5138 int original_height = frame()->height();
5012 #endif 5139 #endif
5013 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 5140 Variable* var = node->target()->AsVariableProxy()->AsVariable();
5014 // Property* prop = node->target()->AsProperty(); 5141 Property* prop = node->target()->AsProperty();
5015 5142
5016 if (var != NULL && !var->is_global()) { 5143 if (var != NULL && !var->is_global()) {
5017 EmitSlotAssignment(node); 5144 EmitSlotAssignment(node);
5018 5145
5146 } else if ((prop != NULL && prop->key()->IsPropertyName()) ||
5147 (var != NULL && var->is_global())) {
5148 // Properties whose keys are property names and global variables are
5149 // treated as named property references. We do not need to consider
5150 // global 'this' because it is not a valid left-hand side.
5151 EmitNamedPropertyAssignment(node);
5152
5019 } else { 5153 } else {
5020 Comment cmnt(masm_, "[ Assignment"); 5154 Comment cmnt(masm_, "[ Assignment");
5021 5155
5022 { Reference target(this, node->target(), node->is_compound()); 5156 { Reference target(this, node->target(), node->is_compound());
5023 if (target.is_illegal()) { 5157 if (target.is_illegal()) {
5024 // Fool the virtual frame into thinking that we left the assignment's 5158 // Fool the virtual frame into thinking that we left the assignment's
5025 // value on the frame. 5159 // value on the frame.
5026 frame_->Push(Smi::FromInt(0)); 5160 frame_->Push(Smi::FromInt(0));
5027 return; 5161 return;
5028 } 5162 }
(...skipping 2811 matching lines...) Expand 10 before | Expand all | Expand 10 after
7840 masm()->movq(result.reg(), FieldOperand(receiver.reg(), offset)); 7974 masm()->movq(result.reg(), FieldOperand(receiver.reg(), offset));
7841 7975
7842 __ IncrementCounter(&Counters::named_load_inline, 1); 7976 __ IncrementCounter(&Counters::named_load_inline, 1);
7843 deferred->BindExit(); 7977 deferred->BindExit();
7844 } 7978 }
7845 ASSERT(frame()->height() == original_height - 1); 7979 ASSERT(frame()->height() == original_height - 1);
7846 return result; 7980 return result;
7847 } 7981 }
7848 7982
7849 7983
7984 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
7985 #ifdef DEBUG
7986 int expected_height = frame()->height() - (is_contextual ? 1 : 2);
7987 #endif
7988
7989 Result result = frame()->CallStoreIC(name, is_contextual);
7990 // A test eax instruction following the call signals that the inobject
7991 // property case was inlined. Ensure that there is not a test eax
7992 // instruction here.
7993 __ nop();
7994
7995 ASSERT_EQ(expected_height, frame()->height());
7996 return result;
7997 }
7998
7999
7850 Result CodeGenerator::EmitKeyedLoad() { 8000 Result CodeGenerator::EmitKeyedLoad() {
7851 #ifdef DEBUG 8001 #ifdef DEBUG
7852 int original_height = frame()->height(); 8002 int original_height = frame()->height();
7853 #endif 8003 #endif
7854 Result result; 8004 Result result;
7855 // Inline array load code if inside of a loop. We do not know 8005 // Inline array load code if inside of a loop. We do not know
7856 // the receiver map yet, so we initially generate the code with 8006 // the receiver map yet, so we initially generate the code with
7857 // a check against an invalid map. In the inline cache code, we 8007 // a check against an invalid map. In the inline cache code, we
7858 // patch the map check if appropriate. 8008 // patch the map check if appropriate.
7859 if (loop_nesting() > 0) { 8009 if (loop_nesting() > 0) {
(...skipping 4310 matching lines...) Expand 10 before | Expand all | Expand 10 after
12170 #undef __ 12320 #undef __
12171 12321
12172 void RecordWriteStub::Generate(MacroAssembler* masm) { 12322 void RecordWriteStub::Generate(MacroAssembler* masm) {
12173 masm->RecordWriteHelper(object_, addr_, scratch_); 12323 masm->RecordWriteHelper(object_, addr_, scratch_);
12174 masm->ret(0); 12324 masm->ret(0);
12175 } 12325 }
12176 12326
12177 } } // namespace v8::internal 12327 } } // namespace v8::internal
12178 12328
12179 #endif // V8_TARGET_ARCH_X64 12329 #endif // V8_TARGET_ARCH_X64
OLDNEW
« 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