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

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

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