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

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

Issue 3028015: Add EmitKeyedStore and EmitKeyedPropertyAssignment to x64. Removal of Refere... (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 5115 matching lines...) Expand 10 before | Expand all | Expand 10 after
5126 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); 5126 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
5127 } 5127 }
5128 5128
5129 // Stack layout: 5129 // Stack layout:
5130 // [tos] : result 5130 // [tos] : result
5131 5131
5132 ASSERT_EQ(frame()->height(), original_height + 1); 5132 ASSERT_EQ(frame()->height(), original_height + 1);
5133 } 5133 }
5134 5134
5135 5135
5136 void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
5137 #ifdef DEBUG
5138 int original_height = frame()->height();
5139 #endif
5140 Comment cmnt(masm_, "[ Keyed Property Assignment");
5141 Property* prop = node->target()->AsProperty();
5142 ASSERT_NOT_NULL(prop);
5143
5144 // Evaluate the receiver subexpression.
5145 Load(prop->obj());
5146
5147 // Change to slow case in the beginning of an initialization block to
5148 // avoid the quadratic behavior of repeatedly adding fast properties.
5149 if (node->starts_initialization_block()) {
5150 frame_->Dup();
5151 Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1);
5152 }
5153
5154 // Change to fast case at the end of an initialization block. To prepare for
5155 // that add an extra copy of the receiver to the frame, so that it can be
5156 // converted back to fast case after the assignment.
5157 if (node->ends_initialization_block()) {
5158 frame_->Dup();
5159 }
5160
5161 // Evaluate the key subexpression.
5162 Load(prop->key());
5163
5164 // Stack layout:
5165 // [tos] : key
5166 // [tos+1] : receiver
5167 // [tos+2] : receiver if at the end of an initialization block
5168
5169 // Evaluate the right-hand side.
5170 if (node->is_compound()) {
5171 // For a compound assignment the right-hand side is a binary operation
5172 // between the current property value and the actual right-hand side.
5173 // Duplicate receiver and key for loading the current property value.
5174 frame()->PushElementAt(1);
5175 frame()->PushElementAt(1);
5176 Result value = EmitKeyedLoad();
5177 frame()->Push(&value);
5178 Load(node->value());
5179
5180 // Perform the binary operation.
5181 bool overwrite_value =
5182 (node->value()->AsBinaryOperation() != NULL &&
5183 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
5184 BinaryOperation expr(node, node->binary_op(), node->target(),
5185 node->value());
5186 GenericBinaryOperation(&expr,
5187 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
5188 } else {
5189 // For non-compound assignment just load the right-hand side.
5190 Load(node->value());
5191 }
5192
5193 // Stack layout:
5194 // [tos] : value
5195 // [tos+1] : key
5196 // [tos+2] : receiver
5197 // [tos+3] : receiver if at the end of an initialization block
5198
5199 // Perform the assignment. It is safe to ignore constants here.
5200 ASSERT(node->op() != Token::INIT_CONST);
5201 CodeForSourcePosition(node->position());
5202 Result answer = EmitKeyedStore(prop->key()->type());
5203 frame()->Push(&answer);
5204
5205 // Stack layout:
5206 // [tos] : result
5207 // [tos+1] : receiver if at the end of an initialization block
5208
5209 // Change to fast case at the end of an initialization block.
5210 if (node->ends_initialization_block()) {
5211 // The argument to the runtime call is the extra copy of the receiver,
5212 // which is below the value of the assignment. Swap the receiver and
5213 // the value of the assignment expression.
5214 Result result = frame()->Pop();
5215 Result receiver = frame()->Pop();
5216 frame()->Push(&result);
5217 frame()->Push(&receiver);
5218 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
5219 }
5220
5221 // Stack layout:
5222 // [tos] : result
5223
5224 ASSERT(frame()->height() == original_height + 1);
5225 }
5226
5227
5136 void CodeGenerator::VisitAssignment(Assignment* node) { 5228 void CodeGenerator::VisitAssignment(Assignment* node) {
5137 #ifdef DEBUG 5229 #ifdef DEBUG
5138 int original_height = frame()->height(); 5230 int original_height = frame()->height();
5139 #endif 5231 #endif
5140 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 5232 Variable* var = node->target()->AsVariableProxy()->AsVariable();
5141 Property* prop = node->target()->AsProperty(); 5233 Property* prop = node->target()->AsProperty();
5142 5234
5143 if (var != NULL && !var->is_global()) { 5235 if (var != NULL && !var->is_global()) {
5144 EmitSlotAssignment(node); 5236 EmitSlotAssignment(node);
5145 5237
5146 } else if ((prop != NULL && prop->key()->IsPropertyName()) || 5238 } else if ((prop != NULL && prop->key()->IsPropertyName()) ||
5147 (var != NULL && var->is_global())) { 5239 (var != NULL && var->is_global())) {
5148 // Properties whose keys are property names and global variables are 5240 // Properties whose keys are property names and global variables are
5149 // treated as named property references. We do not need to consider 5241 // treated as named property references. We do not need to consider
5150 // global 'this' because it is not a valid left-hand side. 5242 // global 'this' because it is not a valid left-hand side.
5151 EmitNamedPropertyAssignment(node); 5243 EmitNamedPropertyAssignment(node);
5152 5244
5245 } else if (prop != NULL) {
5246 // Other properties (including rewritten parameters for a function that
5247 // uses arguments) are keyed property assignments.
5248 EmitKeyedPropertyAssignment(node);
5249
5153 } else { 5250 } else {
5154 Comment cmnt(masm_, "[ Assignment"); 5251 // Invalid left-hand side.
5155 5252 Load(node->target());
5156 { Reference target(this, node->target(), node->is_compound()); 5253 Result result = frame()->CallRuntime(Runtime::kThrowReferenceError, 1);
5157 if (target.is_illegal()) { 5254 // The runtime call doesn't actually return but the code generator will
5158 // Fool the virtual frame into thinking that we left the assignment's 5255 // still generate code and expects a certain frame height.
5159 // value on the frame. 5256 frame()->Push(&result);
5160 frame_->Push(Smi::FromInt(0));
5161 return;
5162 }
5163
5164 if (node->starts_initialization_block()) {
5165 ASSERT(target.type() == Reference::NAMED ||
5166 target.type() == Reference::KEYED);
5167 // Change to slow case in the beginning of an initialization
5168 // block to avoid the quadratic behavior of repeatedly adding
5169 // fast properties.
5170
5171 // The receiver is the argument to the runtime call. It is the
5172 // first value pushed when the reference was loaded to the
5173 // frame.
5174 frame_->PushElementAt(target.size() - 1);
5175 Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1);
5176 }
5177 if (node->ends_initialization_block()) {
5178 // Add an extra copy of the receiver to the frame, so that it can be
5179 // converted back to fast case after the assignment.
5180 ASSERT(target.type() == Reference::NAMED ||
5181 target.type() == Reference::KEYED);
5182 if (target.type() == Reference::NAMED) {
5183 frame_->Dup();
5184 // Dup target receiver on stack.
5185 } else {
5186 ASSERT(target.type() == Reference::KEYED);
5187 Result temp = frame_->Pop();
5188 frame_->Dup();
5189 frame_->Push(&temp);
5190 }
5191 }
5192 if (node->op() == Token::ASSIGN ||
5193 node->op() == Token::INIT_VAR ||
5194 node->op() == Token::INIT_CONST) {
5195 Load(node->value());
5196
5197 } else { // Assignment is a compound assignment.
5198 Literal* literal = node->value()->AsLiteral();
5199 bool overwrite_value =
5200 (node->value()->AsBinaryOperation() != NULL &&
5201 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
5202 Variable* right_var = node->value()->AsVariableProxy()->AsVariable();
5203 // There are two cases where the target is not read in the right hand
5204 // side, that are easy to test for: the right hand side is a literal,
5205 // or the right hand side is a different variable. TakeValue
5206 // invalidates the target, with an implicit promise that it will be
5207 // written to again
5208 // before it is read.
5209 if (literal != NULL || (right_var != NULL && right_var != var)) {
5210 target.TakeValue();
5211 } else {
5212 target.GetValue();
5213 }
5214 Load(node->value());
5215 BinaryOperation expr(node, node->binary_op(), node->target(),
5216 node->value());
5217 GenericBinaryOperation(
5218 &expr, overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
5219 }
5220 if (var != NULL &&
5221 var->mode() == Variable::CONST &&
5222 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
5223 // Assignment ignored - leave the value on the stack.
5224 UnloadReference(&target);
5225 } else {
5226 CodeForSourcePosition(node->position());
5227 if (node->op() == Token::INIT_CONST) {
5228 // Dynamic constant initializations must use the function context
5229 // and initialize the actual constant declared. Dynamic variable
5230 // initializations are simply assignments and use SetValue.
5231 target.SetValue(CONST_INIT);
5232 } else {
5233 target.SetValue(NOT_CONST_INIT);
5234 }
5235 if (node->ends_initialization_block()) {
5236 ASSERT(target.type() == Reference::UNLOADED);
5237 // End of initialization block. Revert to fast case. The
5238 // argument to the runtime call is the extra copy of the receiver,
5239 // which is below the value of the assignment.
5240 // Swap the receiver and the value of the assignment expression.
5241 Result lhs = frame_->Pop();
5242 Result receiver = frame_->Pop();
5243 frame_->Push(&lhs);
5244 frame_->Push(&receiver);
5245 Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
5246 }
5247 }
5248 }
5249 } 5257 }
5250 // Stack layout:
5251 // [tos] : result
5252 5258
5253 ASSERT(frame()->height() == original_height + 1); 5259 ASSERT(frame()->height() == original_height + 1);
5254 } 5260 }
5255 5261
5256 5262
5257 void CodeGenerator::VisitThrow(Throw* node) { 5263 void CodeGenerator::VisitThrow(Throw* node) {
5258 Comment cmnt(masm_, "[ Throw"); 5264 Comment cmnt(masm_, "[ Throw");
5259 Load(node->exception()); 5265 Load(node->exception());
5260 Result result = frame_->CallRuntime(Runtime::kThrow, 1); 5266 Result result = frame_->CallRuntime(Runtime::kThrow, 1);
5261 frame_->Push(&result); 5267 frame_->Push(&result);
(...skipping 2828 matching lines...) Expand 10 before | Expand all | Expand 10 after
8090 // indicate that we have generated an inline version of the 8096 // indicate that we have generated an inline version of the
8091 // keyed load. The explicit nop instruction is here because 8097 // keyed load. The explicit nop instruction is here because
8092 // the push that follows might be peep-hole optimized away. 8098 // the push that follows might be peep-hole optimized away.
8093 __ nop(); 8099 __ nop();
8094 } 8100 }
8095 ASSERT(frame()->height() == original_height - 2); 8101 ASSERT(frame()->height() == original_height - 2);
8096 return result; 8102 return result;
8097 } 8103 }
8098 8104
8099 8105
8106 Result CodeGenerator::EmitKeyedStore(StaticType* key_type) {
8107 #ifdef DEBUG
8108 int original_height = frame()->height();
8109 #endif
8110 Result result;
8111 // Generate inlined version of the keyed store if the code is in a loop
8112 // and the key is likely to be a smi.
8113 if (loop_nesting() > 0 && key_type->IsLikelySmi()) {
8114 Comment cmnt(masm(), "[ Inlined store to keyed Property");
8115
8116 // Get the receiver, key and value into registers.
8117 result = frame()->Pop();
8118 Result key = frame()->Pop();
8119 Result receiver = frame()->Pop();
8120
8121 Result tmp = allocator_->Allocate();
8122 ASSERT(tmp.is_valid());
8123 Result tmp2 = allocator_->Allocate();
8124 ASSERT(tmp2.is_valid());
8125
8126 // Determine whether the value is a constant before putting it in a
8127 // register.
8128 bool value_is_constant = result.is_constant();
8129
8130 // Make sure that value, key and receiver are in registers.
8131 result.ToRegister();
8132 key.ToRegister();
8133 receiver.ToRegister();
8134
8135 DeferredReferenceSetKeyedValue* deferred =
8136 new DeferredReferenceSetKeyedValue(result.reg(),
8137 key.reg(),
8138 receiver.reg());
8139
8140 // Check that the receiver is not a smi.
8141 __ JumpIfSmi(receiver.reg(), deferred->entry_label());
8142
8143 // Check that the key is a smi.
8144 if (!key.is_smi()) {
8145 __ JumpIfNotSmi(key.reg(), deferred->entry_label());
8146 } else if (FLAG_debug_code) {
8147 __ AbortIfNotSmi(key.reg());
8148 }
8149
8150 // Check that the receiver is a JSArray.
8151 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister);
8152 deferred->Branch(not_equal);
8153
8154 // Check that the key is within bounds. Both the key and the length of
8155 // the JSArray are smis. Use unsigned comparison to handle negative keys.
8156 __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
8157 key.reg());
8158 deferred->Branch(below_equal);
8159
8160 // Get the elements array from the receiver and check that it is not a
8161 // dictionary.
8162 __ movq(tmp.reg(),
8163 FieldOperand(receiver.reg(), JSArray::kElementsOffset));
8164
8165 // Check whether it is possible to omit the write barrier. If the elements
8166 // array is in new space or the value written is a smi we can safely update
8167 // the elements array without write barrier.
8168 Label in_new_space;
8169 __ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space);
8170 if (!value_is_constant) {
8171 __ JumpIfNotSmi(result.reg(), deferred->entry_label());
8172 }
8173
8174 __ bind(&in_new_space);
8175 // Bind the deferred code patch site to be able to locate the fixed
8176 // array map comparison. When debugging, we patch this comparison to
8177 // always fail so that we will hit the IC call in the deferred code
8178 // which will allow the debugger to break for fast case stores.
8179 __ bind(deferred->patch_site());
8180 // Avoid using __ to ensure the distance from patch_site
8181 // to the map address is always the same.
8182 masm()->movq(kScratchRegister, Factory::fixed_array_map(),
8183 RelocInfo::EMBEDDED_OBJECT);
8184 __ cmpq(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
8185 kScratchRegister);
8186 deferred->Branch(not_equal);
8187
8188 // Store the value.
8189 SmiIndex index =
8190 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2);
8191 __ movq(FieldOperand(tmp.reg(),
8192 index.reg,
8193 index.scale,
8194 FixedArray::kHeaderSize),
8195 result.reg());
8196 __ IncrementCounter(&Counters::keyed_store_inline, 1);
8197
8198 deferred->BindExit();
8199 } else {
8200 result = frame()->CallKeyedStoreIC();
8201 // Make sure that we do not have a test instruction after the
8202 // call. A test instruction after the call is used to
8203 // indicate that we have generated an inline version of the
8204 // keyed store.
8205 __ nop();
8206 }
8207 ASSERT(frame()->height() == original_height - 3);
8208 return result;
8209 }
8210
8211
8100 #undef __ 8212 #undef __
8101 #define __ ACCESS_MASM(masm) 8213 #define __ ACCESS_MASM(masm)
8102 8214
8103 8215
8104 Handle<String> Reference::GetName() { 8216 Handle<String> Reference::GetName() {
8105 ASSERT(type_ == NAMED); 8217 ASSERT(type_ == NAMED);
8106 Property* property = expression_->AsProperty(); 8218 Property* property = expression_->AsProperty();
8107 if (property == NULL) { 8219 if (property == NULL) {
8108 // Global variable reference treated as a named property reference. 8220 // Global variable reference treated as a named property reference.
8109 VariableProxy* proxy = expression_->AsVariableProxy(); 8221 VariableProxy* proxy = expression_->AsVariableProxy();
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
8215 void Reference::SetValue(InitState init_state) { 8327 void Reference::SetValue(InitState init_state) {
8216 ASSERT(cgen_->HasValidEntryRegisters()); 8328 ASSERT(cgen_->HasValidEntryRegisters());
8217 ASSERT(!is_illegal()); 8329 ASSERT(!is_illegal());
8218 MacroAssembler* masm = cgen_->masm(); 8330 MacroAssembler* masm = cgen_->masm();
8219 switch (type_) { 8331 switch (type_) {
8220 case SLOT: { 8332 case SLOT: {
8221 Comment cmnt(masm, "[ Store to Slot"); 8333 Comment cmnt(masm, "[ Store to Slot");
8222 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 8334 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
8223 ASSERT(slot != NULL); 8335 ASSERT(slot != NULL);
8224 cgen_->StoreToSlot(slot, init_state); 8336 cgen_->StoreToSlot(slot, init_state);
8225 cgen_->UnloadReference(this); 8337 set_unloaded();
8226 break; 8338 break;
8227 } 8339 }
8228 8340
8229 case NAMED: { 8341 case NAMED: {
8230 Comment cmnt(masm, "[ Store to named Property"); 8342 Comment cmnt(masm, "[ Store to named Property");
8231 cgen_->frame()->Push(GetName()); 8343 Result answer = cgen_->EmitNamedStore(GetName(), false);
8232 Result answer = cgen_->frame()->CallStoreIC();
8233 cgen_->frame()->Push(&answer); 8344 cgen_->frame()->Push(&answer);
8234 set_unloaded(); 8345 set_unloaded();
8235 break; 8346 break;
8236 } 8347 }
8237 8348
8238 case KEYED: { 8349 case KEYED: {
8239 Comment cmnt(masm, "[ Store to keyed Property"); 8350 Comment cmnt(masm, "[ Store to keyed Property");
8240
8241 // Generate inlined version of the keyed store if the code is in
8242 // a loop and the key is likely to be a smi.
8243 Property* property = expression()->AsProperty(); 8351 Property* property = expression()->AsProperty();
8244 ASSERT(property != NULL); 8352 ASSERT(property != NULL);
8245 StaticType* key_smi_analysis = property->key()->type();
8246 8353
8247 if (cgen_->loop_nesting() > 0 && key_smi_analysis->IsLikelySmi()) { 8354 Result answer = cgen_->EmitKeyedStore(property->key()->type());
8248 Comment cmnt(masm, "[ Inlined store to keyed Property"); 8355 cgen_->frame()->Push(&answer);
8249
8250 // Get the receiver, key and value into registers.
8251 Result value = cgen_->frame()->Pop();
8252 Result key = cgen_->frame()->Pop();
8253 Result receiver = cgen_->frame()->Pop();
8254
8255 Result tmp = cgen_->allocator_->Allocate();
8256 ASSERT(tmp.is_valid());
8257 Result tmp2 = cgen_->allocator_->Allocate();
8258 ASSERT(tmp2.is_valid());
8259
8260 // Determine whether the value is a constant before putting it
8261 // in a register.
8262 bool value_is_constant = value.is_constant();
8263
8264 // Make sure that value, key and receiver are in registers.
8265 value.ToRegister();
8266 key.ToRegister();
8267 receiver.ToRegister();
8268
8269 DeferredReferenceSetKeyedValue* deferred =
8270 new DeferredReferenceSetKeyedValue(value.reg(),
8271 key.reg(),
8272 receiver.reg());
8273
8274 // Check that the receiver is not a smi.
8275 __ JumpIfSmi(receiver.reg(), deferred->entry_label());
8276
8277 // Check that the key is a smi.
8278 if (!key.is_smi()) {
8279 __ JumpIfNotSmi(key.reg(), deferred->entry_label());
8280 } else if (FLAG_debug_code) {
8281 __ AbortIfNotSmi(key.reg());
8282 }
8283
8284 // Check that the receiver is a JSArray.
8285 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister);
8286 deferred->Branch(not_equal);
8287
8288 // Check that the key is within bounds. Both the key and the
8289 // length of the JSArray are smis. Use unsigned comparison to handle
8290 // negative keys.
8291 __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
8292 key.reg());
8293 deferred->Branch(below_equal);
8294
8295 // Get the elements array from the receiver and check that it
8296 // is a flat array (not a dictionary).
8297 __ movq(tmp.reg(),
8298 FieldOperand(receiver.reg(), JSObject::kElementsOffset));
8299
8300 // Check whether it is possible to omit the write barrier. If the
8301 // elements array is in new space or the value written is a smi we can
8302 // safely update the elements array without write barrier.
8303 Label in_new_space;
8304 __ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space);
8305 if (!value_is_constant) {
8306 __ JumpIfNotSmi(value.reg(), deferred->entry_label());
8307 }
8308
8309 __ bind(&in_new_space);
8310 // Bind the deferred code patch site to be able to locate the
8311 // fixed array map comparison. When debugging, we patch this
8312 // comparison to always fail so that we will hit the IC call
8313 // in the deferred code which will allow the debugger to
8314 // break for fast case stores.
8315 __ bind(deferred->patch_site());
8316 // Avoid using __ to ensure the distance from patch_site
8317 // to the map address is always the same.
8318 masm->movq(kScratchRegister, Factory::fixed_array_map(),
8319 RelocInfo::EMBEDDED_OBJECT);
8320 __ cmpq(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
8321 kScratchRegister);
8322 deferred->Branch(not_equal);
8323
8324 // Store the value.
8325 SmiIndex index =
8326 masm->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2);
8327 __ movq(FieldOperand(tmp.reg(),
8328 index.reg,
8329 index.scale,
8330 FixedArray::kHeaderSize),
8331 value.reg());
8332 __ IncrementCounter(&Counters::keyed_store_inline, 1);
8333
8334 deferred->BindExit();
8335
8336 cgen_->frame()->Push(&value);
8337 } else {
8338 Result answer = cgen_->frame()->CallKeyedStoreIC();
8339 // Make sure that we do not have a test instruction after the
8340 // call. A test instruction after the call is used to
8341 // indicate that we have generated an inline version of the
8342 // keyed store.
8343 masm->nop();
8344 cgen_->frame()->Push(&answer);
8345 }
8346 set_unloaded(); 8356 set_unloaded();
8347 break; 8357 break;
8348 } 8358 }
8349 8359
8350 default: 8360 case UNLOADED:
8361 case ILLEGAL:
8351 UNREACHABLE(); 8362 UNREACHABLE();
8352 } 8363 }
8353 } 8364 }
8354 8365
8355 8366
8356 void FastNewClosureStub::Generate(MacroAssembler* masm) { 8367 void FastNewClosureStub::Generate(MacroAssembler* masm) {
8357 // Create a new closure from the given function info in new 8368 // Create a new closure from the given function info in new
8358 // space. Set the context to the current context in rsi. 8369 // space. Set the context to the current context in rsi.
8359 Label gc; 8370 Label gc;
8360 __ AllocateInNewSpace(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT); 8371 __ AllocateInNewSpace(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT);
(...skipping 3959 matching lines...) Expand 10 before | Expand all | Expand 10 after
12320 #undef __ 12331 #undef __
12321 12332
12322 void RecordWriteStub::Generate(MacroAssembler* masm) { 12333 void RecordWriteStub::Generate(MacroAssembler* masm) {
12323 masm->RecordWriteHelper(object_, addr_, scratch_); 12334 masm->RecordWriteHelper(object_, addr_, scratch_);
12324 masm->ret(0); 12335 masm->ret(0);
12325 } 12336 }
12326 12337
12327 } } // namespace v8::internal 12338 } } // namespace v8::internal
12328 12339
12329 #endif // V8_TARGET_ARCH_X64 12340 #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