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

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

Issue 7172030: Revert "Merge arguments branch to bleeding merge." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 6 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/code-stubs-x64.cc ('k') | src/x64/ic-x64.cc » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 __ lea(rdx, 219 __ lea(rdx,
220 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); 220 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
221 __ push(rdx); 221 __ push(rdx);
222 __ Push(Smi::FromInt(scope()->num_parameters())); 222 __ Push(Smi::FromInt(scope()->num_parameters()));
223 // Arguments to ArgumentsAccessStub: 223 // Arguments to ArgumentsAccessStub:
224 // function, receiver address, parameter count. 224 // function, receiver address, parameter count.
225 // The stub will rewrite receiver and parameter count if the previous 225 // The stub will rewrite receiver and parameter count if the previous
226 // stack frame was an arguments adapter frame. 226 // stack frame was an arguments adapter frame.
227 ArgumentsAccessStub stub( 227 ArgumentsAccessStub stub(
228 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT 228 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT
229 : ArgumentsAccessStub::NEW_NON_STRICT_SLOW); 229 : ArgumentsAccessStub::NEW_NON_STRICT);
230 __ CallStub(&stub); 230 __ CallStub(&stub);
231 231
232 Variable* arguments_shadow = scope()->arguments_shadow();
233 if (arguments_shadow != NULL) {
234 // Store new arguments object in both "arguments" and ".arguments" slots.
235 __ movq(rcx, rax);
236 Move(arguments_shadow->AsSlot(), rcx, rbx, rdx);
237 }
232 Move(arguments->AsSlot(), rax, rbx, rdx); 238 Move(arguments->AsSlot(), rax, rbx, rdx);
233 } 239 }
234 240
235 if (FLAG_trace) { 241 if (FLAG_trace) {
236 __ CallRuntime(Runtime::kTraceEnter, 0); 242 __ CallRuntime(Runtime::kTraceEnter, 0);
237 } 243 }
238 244
239 // Visit the declarations and body unless there is an illegal 245 // Visit the declarations and body unless there is an illegal
240 // redeclaration. 246 // redeclaration.
241 if (scope()->HasIllegalRedeclaration()) { 247 if (scope()->HasIllegalRedeclaration()) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 370
365 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const { 371 void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
366 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); 372 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
367 __ push(slot_operand); 373 __ push(slot_operand);
368 } 374 }
369 375
370 376
371 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { 377 void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
372 codegen()->Move(result_register(), slot); 378 codegen()->Move(result_register(), slot);
373 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 379 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
374 codegen()->DoTest(true_label_, false_label_, fall_through_); 380 codegen()->DoTest(this);
375 } 381 }
376 382
377 383
378 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 384 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
379 } 385 }
380 386
381 387
382 void FullCodeGenerator::AccumulatorValueContext::Plug( 388 void FullCodeGenerator::AccumulatorValueContext::Plug(
383 Heap::RootListIndex index) const { 389 Heap::RootListIndex index) const {
384 __ LoadRoot(result_register(), index); 390 __ LoadRoot(result_register(), index);
(...skipping 12 matching lines...) Expand all
397 true_label_, 403 true_label_,
398 false_label_); 404 false_label_);
399 if (index == Heap::kUndefinedValueRootIndex || 405 if (index == Heap::kUndefinedValueRootIndex ||
400 index == Heap::kNullValueRootIndex || 406 index == Heap::kNullValueRootIndex ||
401 index == Heap::kFalseValueRootIndex) { 407 index == Heap::kFalseValueRootIndex) {
402 if (false_label_ != fall_through_) __ jmp(false_label_); 408 if (false_label_ != fall_through_) __ jmp(false_label_);
403 } else if (index == Heap::kTrueValueRootIndex) { 409 } else if (index == Heap::kTrueValueRootIndex) {
404 if (true_label_ != fall_through_) __ jmp(true_label_); 410 if (true_label_ != fall_through_) __ jmp(true_label_);
405 } else { 411 } else {
406 __ LoadRoot(result_register(), index); 412 __ LoadRoot(result_register(), index);
407 codegen()->DoTest(true_label_, false_label_, fall_through_); 413 codegen()->DoTest(this);
408 } 414 }
409 } 415 }
410 416
411 417
412 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 418 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
413 } 419 }
414 420
415 421
416 void FullCodeGenerator::AccumulatorValueContext::Plug( 422 void FullCodeGenerator::AccumulatorValueContext::Plug(
417 Handle<Object> lit) const { 423 Handle<Object> lit) const {
(...skipping 24 matching lines...) Expand all
442 } 448 }
443 } else if (lit->IsSmi()) { 449 } else if (lit->IsSmi()) {
444 if (Smi::cast(*lit)->value() == 0) { 450 if (Smi::cast(*lit)->value() == 0) {
445 if (false_label_ != fall_through_) __ jmp(false_label_); 451 if (false_label_ != fall_through_) __ jmp(false_label_);
446 } else { 452 } else {
447 if (true_label_ != fall_through_) __ jmp(true_label_); 453 if (true_label_ != fall_through_) __ jmp(true_label_);
448 } 454 }
449 } else { 455 } else {
450 // For simplicity we always test the accumulator register. 456 // For simplicity we always test the accumulator register.
451 __ Move(result_register(), lit); 457 __ Move(result_register(), lit);
452 codegen()->DoTest(true_label_, false_label_, fall_through_); 458 codegen()->DoTest(this);
453 } 459 }
454 } 460 }
455 461
456 462
457 void FullCodeGenerator::EffectContext::DropAndPlug(int count, 463 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
458 Register reg) const { 464 Register reg) const {
459 ASSERT(count > 0); 465 ASSERT(count > 0);
460 __ Drop(count); 466 __ Drop(count);
461 } 467 }
462 468
(...skipping 15 matching lines...) Expand all
478 } 484 }
479 485
480 486
481 void FullCodeGenerator::TestContext::DropAndPlug(int count, 487 void FullCodeGenerator::TestContext::DropAndPlug(int count,
482 Register reg) const { 488 Register reg) const {
483 ASSERT(count > 0); 489 ASSERT(count > 0);
484 // For simplicity we always test the accumulator register. 490 // For simplicity we always test the accumulator register.
485 __ Drop(count); 491 __ Drop(count);
486 __ Move(result_register(), reg); 492 __ Move(result_register(), reg);
487 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 493 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
488 codegen()->DoTest(true_label_, false_label_, fall_through_); 494 codegen()->DoTest(this);
489 } 495 }
490 496
491 497
492 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 498 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
493 Label* materialize_false) const { 499 Label* materialize_false) const {
494 ASSERT(materialize_true == materialize_false); 500 ASSERT(materialize_true == materialize_false);
495 __ bind(materialize_true); 501 __ bind(materialize_true);
496 } 502 }
497 503
498 504
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 true_label_, 559 true_label_,
554 false_label_); 560 false_label_);
555 if (flag) { 561 if (flag) {
556 if (true_label_ != fall_through_) __ jmp(true_label_); 562 if (true_label_ != fall_through_) __ jmp(true_label_);
557 } else { 563 } else {
558 if (false_label_ != fall_through_) __ jmp(false_label_); 564 if (false_label_ != fall_through_) __ jmp(false_label_);
559 } 565 }
560 } 566 }
561 567
562 568
563 void FullCodeGenerator::DoTest(Label* if_true, 569 void FullCodeGenerator::DoTest(Expression* condition,
570 Label* if_true,
564 Label* if_false, 571 Label* if_false,
565 Label* fall_through) { 572 Label* fall_through) {
566 ToBooleanStub stub; 573 ToBooleanStub stub;
567 __ push(result_register()); 574 __ push(result_register());
568 __ CallStub(&stub); 575 __ CallStub(&stub);
569 __ testq(rax, rax); 576 __ testq(rax, rax);
570 // The stub returns nonzero for true. 577 // The stub returns nonzero for true.
571 Split(not_zero, if_true, if_false, fall_through); 578 Split(not_zero, if_true, if_false, fall_through);
572 } 579 }
573 580
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); 1214 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1208 __ jmp(done); 1215 __ jmp(done);
1209 } 1216 }
1210 } 1217 }
1211 } 1218 }
1212 } 1219 }
1213 } 1220 }
1214 1221
1215 1222
1216 void FullCodeGenerator::EmitVariableLoad(Variable* var) { 1223 void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1217 // Three cases: non-this global variables, lookup slots, and all other 1224 // Four cases: non-this global variables, lookup slots, all other
1218 // types of slots. 1225 // types of slots, and parameters that rewrite to explicit property
1226 // accesses on the arguments object.
1219 Slot* slot = var->AsSlot(); 1227 Slot* slot = var->AsSlot();
1220 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); 1228 Property* property = var->AsProperty();
1221 1229
1222 if (slot == NULL) { 1230 if (var->is_global() && !var->is_this()) {
1223 Comment cmnt(masm_, "Global variable"); 1231 Comment cmnt(masm_, "Global variable");
1224 // Use inline caching. Variable name is passed in rcx and the global 1232 // Use inline caching. Variable name is passed in rcx and the global
1225 // object on the stack. 1233 // object on the stack.
1226 __ Move(rcx, var->name()); 1234 __ Move(rcx, var->name());
1227 __ movq(rax, GlobalObjectOperand()); 1235 __ movq(rax, GlobalObjectOperand());
1228 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1236 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1229 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); 1237 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber);
1230 context()->Plug(rax); 1238 context()->Plug(rax);
1231 1239
1232 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1240 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1233 Label done, slow; 1241 Label done, slow;
1234 1242
1235 // Generate code for loading from variables potentially shadowed 1243 // Generate code for loading from variables potentially shadowed
1236 // by eval-introduced variables. 1244 // by eval-introduced variables.
1237 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 1245 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
1238 1246
1239 __ bind(&slow); 1247 __ bind(&slow);
1240 Comment cmnt(masm_, "Lookup slot"); 1248 Comment cmnt(masm_, "Lookup slot");
1241 __ push(rsi); // Context. 1249 __ push(rsi); // Context.
1242 __ Push(var->name()); 1250 __ Push(var->name());
1243 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1251 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1244 __ bind(&done); 1252 __ bind(&done);
1245 1253
1246 context()->Plug(rax); 1254 context()->Plug(rax);
1247 1255
1248 } else { 1256 } else if (slot != NULL) {
1249 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1257 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1250 ? "Context slot" 1258 ? "Context slot"
1251 : "Stack slot"); 1259 : "Stack slot");
1252 if (var->mode() == Variable::CONST) { 1260 if (var->mode() == Variable::CONST) {
1253 // Constants may be the hole value if they have not been initialized. 1261 // Constants may be the hole value if they have not been initialized.
1254 // Unhole them. 1262 // Unhole them.
1255 Label done; 1263 Label done;
1256 MemOperand slot_operand = EmitSlotSearch(slot, rax); 1264 MemOperand slot_operand = EmitSlotSearch(slot, rax);
1257 __ movq(rax, slot_operand); 1265 __ movq(rax, slot_operand);
1258 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1266 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1259 __ j(not_equal, &done, Label::kNear); 1267 __ j(not_equal, &done, Label::kNear);
1260 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1268 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1261 __ bind(&done); 1269 __ bind(&done);
1262 context()->Plug(rax); 1270 context()->Plug(rax);
1263 } else { 1271 } else {
1264 context()->Plug(slot); 1272 context()->Plug(slot);
1265 } 1273 }
1274
1275 } else {
1276 Comment cmnt(masm_, "Rewritten parameter");
1277 ASSERT_NOT_NULL(property);
1278 // Rewritten parameter accesses are of the form "slot[literal]".
1279
1280 // Assert that the object is in a slot.
1281 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1282 ASSERT_NOT_NULL(object_var);
1283 Slot* object_slot = object_var->AsSlot();
1284 ASSERT_NOT_NULL(object_slot);
1285
1286 // Load the object.
1287 MemOperand object_loc = EmitSlotSearch(object_slot, rax);
1288 __ movq(rdx, object_loc);
1289
1290 // Assert that the key is a smi.
1291 Literal* key_literal = property->key()->AsLiteral();
1292 ASSERT_NOT_NULL(key_literal);
1293 ASSERT(key_literal->handle()->IsSmi());
1294
1295 // Load the key.
1296 __ Move(rax, key_literal->handle());
1297
1298 // Do a keyed property load.
1299 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1300 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1301 context()->Plug(rax);
1266 } 1302 }
1267 } 1303 }
1268 1304
1269 1305
1270 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1306 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1271 Comment cmnt(masm_, "[ RegExpLiteral"); 1307 Comment cmnt(masm_, "[ RegExpLiteral");
1272 Label materialized; 1308 Label materialized;
1273 // Registers will be used as follows: 1309 // Registers will be used as follows:
1274 // rdi = JS function. 1310 // rdi = JS function.
1275 // rcx = literals array. 1311 // rcx = literals array.
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1524 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1489 Comment cmnt(masm_, "[ Assignment"); 1525 Comment cmnt(masm_, "[ Assignment");
1490 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1526 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1491 // on the left-hand side. 1527 // on the left-hand side.
1492 if (!expr->target()->IsValidLeftHandSide()) { 1528 if (!expr->target()->IsValidLeftHandSide()) {
1493 VisitForEffect(expr->target()); 1529 VisitForEffect(expr->target());
1494 return; 1530 return;
1495 } 1531 }
1496 1532
1497 // Left-hand side can only be a property, a global or a (parameter or local) 1533 // Left-hand side can only be a property, a global or a (parameter or local)
1498 // slot. 1534 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1499 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1535 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1500 LhsKind assign_type = VARIABLE; 1536 LhsKind assign_type = VARIABLE;
1501 Property* property = expr->target()->AsProperty(); 1537 Property* property = expr->target()->AsProperty();
1502 if (property != NULL) { 1538 if (property != NULL) {
1503 assign_type = (property->key()->IsPropertyName()) 1539 assign_type = (property->key()->IsPropertyName())
1504 ? NAMED_PROPERTY 1540 ? NAMED_PROPERTY
1505 : KEYED_PROPERTY; 1541 : KEYED_PROPERTY;
1506 } 1542 }
1507 1543
1508 // Evaluate LHS expression. 1544 // Evaluate LHS expression.
1509 switch (assign_type) { 1545 switch (assign_type) {
1510 case VARIABLE: 1546 case VARIABLE:
1511 // Nothing to do here. 1547 // Nothing to do here.
1512 break; 1548 break;
1513 case NAMED_PROPERTY: 1549 case NAMED_PROPERTY:
1514 if (expr->is_compound()) { 1550 if (expr->is_compound()) {
1515 // We need the receiver both on the stack and in the accumulator. 1551 // We need the receiver both on the stack and in the accumulator.
1516 VisitForAccumulatorValue(property->obj()); 1552 VisitForAccumulatorValue(property->obj());
1517 __ push(result_register()); 1553 __ push(result_register());
1518 } else { 1554 } else {
1519 VisitForStackValue(property->obj()); 1555 VisitForStackValue(property->obj());
1520 } 1556 }
1521 break; 1557 break;
1522 case KEYED_PROPERTY: { 1558 case KEYED_PROPERTY: {
1523 if (expr->is_compound()) { 1559 if (expr->is_compound()) {
1524 VisitForStackValue(property->obj()); 1560 if (property->is_arguments_access()) {
1525 VisitForAccumulatorValue(property->key()); 1561 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1562 MemOperand slot_operand =
1563 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1564 __ push(slot_operand);
1565 __ Move(rax, property->key()->AsLiteral()->handle());
1566 } else {
1567 VisitForStackValue(property->obj());
1568 VisitForAccumulatorValue(property->key());
1569 }
1526 __ movq(rdx, Operand(rsp, 0)); 1570 __ movq(rdx, Operand(rsp, 0));
1527 __ push(rax); 1571 __ push(rax);
1528 } else { 1572 } else {
1529 VisitForStackValue(property->obj()); 1573 if (property->is_arguments_access()) {
1530 VisitForStackValue(property->key()); 1574 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1575 MemOperand slot_operand =
1576 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1577 __ push(slot_operand);
1578 __ Push(property->key()->AsLiteral()->handle());
1579 } else {
1580 VisitForStackValue(property->obj());
1581 VisitForStackValue(property->key());
1582 }
1531 } 1583 }
1532 break; 1584 break;
1533 } 1585 }
1534 } 1586 }
1535 1587
1536 // For compound assignments we need another deoptimization point after the 1588 // For compound assignments we need another deoptimization point after the
1537 // variable/property load. 1589 // variable/property load.
1538 if (expr->is_compound()) { 1590 if (expr->is_compound()) {
1539 { AccumulatorValueContext context(this); 1591 { AccumulatorValueContext context(this);
1540 switch (assign_type) { 1592 switch (assign_type) {
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1687 1739
1688 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { 1740 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1689 // Invalid left-hand sides are rewritten to have a 'throw 1741 // Invalid left-hand sides are rewritten to have a 'throw
1690 // ReferenceError' on the left-hand side. 1742 // ReferenceError' on the left-hand side.
1691 if (!expr->IsValidLeftHandSide()) { 1743 if (!expr->IsValidLeftHandSide()) {
1692 VisitForEffect(expr); 1744 VisitForEffect(expr);
1693 return; 1745 return;
1694 } 1746 }
1695 1747
1696 // Left-hand side can only be a property, a global or a (parameter or local) 1748 // Left-hand side can only be a property, a global or a (parameter or local)
1697 // slot. 1749 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1698 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1750 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1699 LhsKind assign_type = VARIABLE; 1751 LhsKind assign_type = VARIABLE;
1700 Property* prop = expr->AsProperty(); 1752 Property* prop = expr->AsProperty();
1701 if (prop != NULL) { 1753 if (prop != NULL) {
1702 assign_type = (prop->key()->IsPropertyName()) 1754 assign_type = (prop->key()->IsPropertyName())
1703 ? NAMED_PROPERTY 1755 ? NAMED_PROPERTY
1704 : KEYED_PROPERTY; 1756 : KEYED_PROPERTY;
1705 } 1757 }
1706 1758
1707 switch (assign_type) { 1759 switch (assign_type) {
(...skipping 10 matching lines...) Expand all
1718 __ pop(rax); // Restore value. 1770 __ pop(rax); // Restore value.
1719 __ Move(rcx, prop->key()->AsLiteral()->handle()); 1771 __ Move(rcx, prop->key()->AsLiteral()->handle());
1720 Handle<Code> ic = is_strict_mode() 1772 Handle<Code> ic = is_strict_mode()
1721 ? isolate()->builtins()->StoreIC_Initialize_Strict() 1773 ? isolate()->builtins()->StoreIC_Initialize_Strict()
1722 : isolate()->builtins()->StoreIC_Initialize(); 1774 : isolate()->builtins()->StoreIC_Initialize();
1723 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 1775 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber);
1724 break; 1776 break;
1725 } 1777 }
1726 case KEYED_PROPERTY: { 1778 case KEYED_PROPERTY: {
1727 __ push(rax); // Preserve value. 1779 __ push(rax); // Preserve value.
1728 VisitForStackValue(prop->obj()); 1780 if (prop->is_synthetic()) {
1729 VisitForAccumulatorValue(prop->key()); 1781 ASSERT(prop->obj()->AsVariableProxy() != NULL);
1730 __ movq(rcx, rax); 1782 ASSERT(prop->key()->AsLiteral() != NULL);
1731 __ pop(rdx); 1783 { AccumulatorValueContext for_object(this);
1784 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1785 }
1786 __ movq(rdx, rax);
1787 __ Move(rcx, prop->key()->AsLiteral()->handle());
1788 } else {
1789 VisitForStackValue(prop->obj());
1790 VisitForAccumulatorValue(prop->key());
1791 __ movq(rcx, rax);
1792 __ pop(rdx);
1793 }
1732 __ pop(rax); // Restore value. 1794 __ pop(rax); // Restore value.
1733 Handle<Code> ic = is_strict_mode() 1795 Handle<Code> ic = is_strict_mode()
1734 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 1796 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
1735 : isolate()->builtins()->KeyedStoreIC_Initialize(); 1797 : isolate()->builtins()->KeyedStoreIC_Initialize();
1736 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); 1798 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber);
1737 break; 1799 break;
1738 } 1800 }
1739 } 1801 }
1740 PrepareForBailoutForId(bailout_ast_id, TOS_REG); 1802 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1741 context()->Plug(rax); 1803 context()->Plug(rax);
1742 } 1804 }
1743 1805
1744 1806
1745 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1807 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1746 Token::Value op) { 1808 Token::Value op) {
1809 // Left-hand sides that rewrite to explicit property accesses do not reach
1810 // here.
1747 ASSERT(var != NULL); 1811 ASSERT(var != NULL);
1748 ASSERT(var->is_global() || var->AsSlot() != NULL); 1812 ASSERT(var->is_global() || var->AsSlot() != NULL);
1749 1813
1750 if (var->is_global()) { 1814 if (var->is_global()) {
1751 ASSERT(!var->is_this()); 1815 ASSERT(!var->is_this());
1752 // Assignment to a global variable. Use inline caching for the 1816 // Assignment to a global variable. Use inline caching for the
1753 // assignment. Right-hand-side value is passed in rax, variable name in 1817 // assignment. Right-hand-side value is passed in rax, variable name in
1754 // rcx, and the global object on the stack. 1818 // rcx, and the global object on the stack.
1755 __ Move(rcx, var->name()); 1819 __ Move(rcx, var->name());
1756 __ movq(rdx, GlobalObjectOperand()); 1820 __ movq(rdx, GlobalObjectOperand());
(...skipping 1934 matching lines...) Expand 10 before | Expand all | Expand 10 after
3691 SetSourcePosition(expr->position()); 3755 SetSourcePosition(expr->position());
3692 3756
3693 // Invalid left-hand-sides are rewritten to have a 'throw 3757 // Invalid left-hand-sides are rewritten to have a 'throw
3694 // ReferenceError' as the left-hand side. 3758 // ReferenceError' as the left-hand side.
3695 if (!expr->expression()->IsValidLeftHandSide()) { 3759 if (!expr->expression()->IsValidLeftHandSide()) {
3696 VisitForEffect(expr->expression()); 3760 VisitForEffect(expr->expression());
3697 return; 3761 return;
3698 } 3762 }
3699 3763
3700 // Expression can only be a property, a global or a (parameter or local) 3764 // Expression can only be a property, a global or a (parameter or local)
3701 // slot. 3765 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
3702 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 3766 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3703 LhsKind assign_type = VARIABLE; 3767 LhsKind assign_type = VARIABLE;
3704 Property* prop = expr->expression()->AsProperty(); 3768 Property* prop = expr->expression()->AsProperty();
3705 // In case of a property we use the uninitialized expression context 3769 // In case of a property we use the uninitialized expression context
3706 // of the key to detect a named property. 3770 // of the key to detect a named property.
3707 if (prop != NULL) { 3771 if (prop != NULL) {
3708 assign_type = 3772 assign_type =
3709 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 3773 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3710 } 3774 }
3711 3775
3712 // Evaluate expression and get value. 3776 // Evaluate expression and get value.
3713 if (assign_type == VARIABLE) { 3777 if (assign_type == VARIABLE) {
3714 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 3778 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
3715 AccumulatorValueContext context(this); 3779 AccumulatorValueContext context(this);
3716 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); 3780 EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3717 } else { 3781 } else {
3718 // Reserve space for result of postfix operation. 3782 // Reserve space for result of postfix operation.
3719 if (expr->is_postfix() && !context()->IsEffect()) { 3783 if (expr->is_postfix() && !context()->IsEffect()) {
3720 __ Push(Smi::FromInt(0)); 3784 __ Push(Smi::FromInt(0));
3721 } 3785 }
3722 if (assign_type == NAMED_PROPERTY) { 3786 if (assign_type == NAMED_PROPERTY) {
3723 VisitForAccumulatorValue(prop->obj()); 3787 VisitForAccumulatorValue(prop->obj());
3724 __ push(rax); // Copy of receiver, needed for later store. 3788 __ push(rax); // Copy of receiver, needed for later store.
3725 EmitNamedPropertyLoad(prop); 3789 EmitNamedPropertyLoad(prop);
3726 } else { 3790 } else {
3727 VisitForStackValue(prop->obj()); 3791 if (prop->is_arguments_access()) {
3728 VisitForAccumulatorValue(prop->key()); 3792 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy();
3793 MemOperand slot_operand =
3794 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
3795 __ push(slot_operand);
3796 __ Move(rax, prop->key()->AsLiteral()->handle());
3797 } else {
3798 VisitForStackValue(prop->obj());
3799 VisitForAccumulatorValue(prop->key());
3800 }
3729 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 3801 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack
3730 __ push(rax); // Copy of key, needed for later store. 3802 __ push(rax); // Copy of key, needed for later store.
3731 EmitKeyedPropertyLoad(prop); 3803 EmitKeyedPropertyLoad(prop);
3732 } 3804 }
3733 } 3805 }
3734 3806
3735 // We need a second deoptimization point after loading the value 3807 // We need a second deoptimization point after loading the value
3736 // in case evaluating the property load my have a side effect. 3808 // in case evaluating the property load my have a side effect.
3737 if (assign_type == VARIABLE) { 3809 if (assign_type == VARIABLE) {
3738 PrepareForBailout(expr->expression(), TOS_REG); 3810 PrepareForBailout(expr->expression(), TOS_REG);
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
4237 __ ret(0); 4309 __ ret(0);
4238 } 4310 }
4239 4311
4240 4312
4241 #undef __ 4313 #undef __
4242 4314
4243 4315
4244 } } // namespace v8::internal 4316 } } // namespace v8::internal
4245 4317
4246 #endif // V8_TARGET_ARCH_X64 4318 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698