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

Side by Side Diff: src/ia32/full-codegen-ia32.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/ia32/code-stubs-ia32.cc ('k') | src/ia32/ic-ia32.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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 __ push(edi); 211 __ push(edi);
212 } else { 212 } else {
213 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 213 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
214 } 214 }
215 // Receiver is just before the parameters on the caller's stack. 215 // Receiver is just before the parameters on the caller's stack.
216 int offset = scope()->num_parameters() * kPointerSize; 216 int offset = scope()->num_parameters() * kPointerSize;
217 __ lea(edx, 217 __ lea(edx,
218 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); 218 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
219 __ push(edx); 219 __ push(edx);
220 __ SafePush(Immediate(Smi::FromInt(scope()->num_parameters()))); 220 __ SafePush(Immediate(Smi::FromInt(scope()->num_parameters())));
221 // Arguments to ArgumentsAccessStub: 221 // Arguments to ArgumentsAccessStub and/or New...:
222 // function, receiver address, parameter count. 222 // function, receiver address, parameter count.
223 // The stub will rewrite receiver and parameter count if the previous 223 // The stub will rewrite receiver and parameter count if the previous
224 // stack frame was an arguments adapter frame. 224 // stack frame was an arguments adapter frame.
225 ArgumentsAccessStub stub( 225 ArgumentsAccessStub::Type type;
226 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT 226 if (is_strict_mode()) {
227 : ArgumentsAccessStub::NEW_NON_STRICT); 227 type = ArgumentsAccessStub::NEW_STRICT;
228 } else if (function()->has_duplicate_parameters()) {
229 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
230 } else {
231 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
232 }
233 ArgumentsAccessStub stub(type);
228 __ CallStub(&stub); 234 __ CallStub(&stub);
229 235
230 Variable* arguments_shadow = scope()->arguments_shadow();
231 if (arguments_shadow != NULL) {
232 __ mov(ecx, eax); // Duplicate result.
233 Move(arguments_shadow->AsSlot(), ecx, ebx, edx);
234 }
235 Move(arguments->AsSlot(), eax, ebx, edx); 236 Move(arguments->AsSlot(), eax, ebx, edx);
236 } 237 }
237 238
238 if (FLAG_trace) { 239 if (FLAG_trace) {
239 __ CallRuntime(Runtime::kTraceEnter, 0); 240 __ CallRuntime(Runtime::kTraceEnter, 0);
240 } 241 }
241 242
242 // Visit the declarations and body unless there is an illegal 243 // Visit the declarations and body unless there is an illegal
243 // redeclaration. 244 // redeclaration.
244 if (scope()->HasIllegalRedeclaration()) { 245 if (scope()->HasIllegalRedeclaration()) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); 368 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
368 // Memory operands can be pushed directly. 369 // Memory operands can be pushed directly.
369 __ push(slot_operand); 370 __ push(slot_operand);
370 } 371 }
371 372
372 373
373 void FullCodeGenerator::TestContext::Plug(Slot* slot) const { 374 void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
374 // For simplicity we always test the accumulator register. 375 // For simplicity we always test the accumulator register.
375 codegen()->Move(result_register(), slot); 376 codegen()->Move(result_register(), slot);
376 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 377 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
377 codegen()->DoTest(this); 378 codegen()->DoTest(true_label_, false_label_, fall_through_);
378 } 379 }
379 380
380 381
381 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 382 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
382 UNREACHABLE(); // Not used on IA32. 383 UNREACHABLE(); // Not used on IA32.
383 } 384 }
384 385
385 386
386 void FullCodeGenerator::AccumulatorValueContext::Plug( 387 void FullCodeGenerator::AccumulatorValueContext::Plug(
387 Heap::RootListIndex index) const { 388 Heap::RootListIndex index) const {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 } 442 }
442 } else if (lit->IsSmi()) { 443 } else if (lit->IsSmi()) {
443 if (Smi::cast(*lit)->value() == 0) { 444 if (Smi::cast(*lit)->value() == 0) {
444 if (false_label_ != fall_through_) __ jmp(false_label_); 445 if (false_label_ != fall_through_) __ jmp(false_label_);
445 } else { 446 } else {
446 if (true_label_ != fall_through_) __ jmp(true_label_); 447 if (true_label_ != fall_through_) __ jmp(true_label_);
447 } 448 }
448 } else { 449 } else {
449 // For simplicity we always test the accumulator register. 450 // For simplicity we always test the accumulator register.
450 __ mov(result_register(), lit); 451 __ mov(result_register(), lit);
451 codegen()->DoTest(this); 452 codegen()->DoTest(true_label_, false_label_, fall_through_);
452 } 453 }
453 } 454 }
454 455
455 456
456 void FullCodeGenerator::EffectContext::DropAndPlug(int count, 457 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
457 Register reg) const { 458 Register reg) const {
458 ASSERT(count > 0); 459 ASSERT(count > 0);
459 __ Drop(count); 460 __ Drop(count);
460 } 461 }
461 462
(...skipping 15 matching lines...) Expand all
477 } 478 }
478 479
479 480
480 void FullCodeGenerator::TestContext::DropAndPlug(int count, 481 void FullCodeGenerator::TestContext::DropAndPlug(int count,
481 Register reg) const { 482 Register reg) const {
482 ASSERT(count > 0); 483 ASSERT(count > 0);
483 // For simplicity we always test the accumulator register. 484 // For simplicity we always test the accumulator register.
484 __ Drop(count); 485 __ Drop(count);
485 __ Move(result_register(), reg); 486 __ Move(result_register(), reg);
486 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 487 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
487 codegen()->DoTest(this); 488 codegen()->DoTest(true_label_, false_label_, fall_through_);
488 } 489 }
489 490
490 491
491 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 492 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
492 Label* materialize_false) const { 493 Label* materialize_false) const {
493 ASSERT(materialize_true == materialize_false); 494 ASSERT(materialize_true == materialize_false);
494 __ bind(materialize_true); 495 __ bind(materialize_true);
495 } 496 }
496 497
497 498
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 true_label_, 555 true_label_,
555 false_label_); 556 false_label_);
556 if (flag) { 557 if (flag) {
557 if (true_label_ != fall_through_) __ jmp(true_label_); 558 if (true_label_ != fall_through_) __ jmp(true_label_);
558 } else { 559 } else {
559 if (false_label_ != fall_through_) __ jmp(false_label_); 560 if (false_label_ != fall_through_) __ jmp(false_label_);
560 } 561 }
561 } 562 }
562 563
563 564
564 void FullCodeGenerator::DoTest(Expression* condition, 565 void FullCodeGenerator::DoTest(Label* if_true,
565 Label* if_true,
566 Label* if_false, 566 Label* if_false,
567 Label* fall_through) { 567 Label* fall_through) {
568 ToBooleanStub stub; 568 ToBooleanStub stub;
569 __ push(result_register()); 569 __ push(result_register());
570 __ CallStub(&stub); 570 __ CallStub(&stub);
571 __ test(eax, Operand(eax)); 571 __ test(eax, Operand(eax));
572 // The stub returns nonzero for true. 572 // The stub returns nonzero for true.
573 Split(not_zero, if_true, if_false, fall_through); 573 Split(not_zero, if_true, if_false, fall_through);
574 } 574 }
575 575
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
1202 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); 1202 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1203 __ jmp(done); 1203 __ jmp(done);
1204 } 1204 }
1205 } 1205 }
1206 } 1206 }
1207 } 1207 }
1208 } 1208 }
1209 1209
1210 1210
1211 void FullCodeGenerator::EmitVariableLoad(Variable* var) { 1211 void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1212 // Four cases: non-this global variables, lookup slots, all other 1212 // Three cases: non-this global variables, lookup slots, and all other
1213 // types of slots, and parameters that rewrite to explicit property 1213 // types of slots.
1214 // accesses on the arguments object.
1215 Slot* slot = var->AsSlot(); 1214 Slot* slot = var->AsSlot();
1216 Property* property = var->AsProperty(); 1215 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
1217 1216
1218 if (var->is_global() && !var->is_this()) { 1217 if (slot == NULL) {
1219 Comment cmnt(masm_, "Global variable"); 1218 Comment cmnt(masm_, "Global variable");
1220 // Use inline caching. Variable name is passed in ecx and the global 1219 // Use inline caching. Variable name is passed in ecx and the global
1221 // object on the stack. 1220 // object on the stack.
1222 __ mov(eax, GlobalObjectOperand()); 1221 __ mov(eax, GlobalObjectOperand());
1223 __ mov(ecx, var->name()); 1222 __ mov(ecx, var->name());
1224 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1223 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1225 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); 1224 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber);
1226 context()->Plug(eax); 1225 context()->Plug(eax);
1227 1226
1228 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1227 } else if (slot->type() == Slot::LOOKUP) {
1229 Label done, slow; 1228 Label done, slow;
1230 1229
1231 // Generate code for loading from variables potentially shadowed 1230 // Generate code for loading from variables potentially shadowed
1232 // by eval-introduced variables. 1231 // by eval-introduced variables.
1233 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 1232 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
1234 1233
1235 __ bind(&slow); 1234 __ bind(&slow);
1236 Comment cmnt(masm_, "Lookup slot"); 1235 Comment cmnt(masm_, "Lookup slot");
1237 __ push(esi); // Context. 1236 __ push(esi); // Context.
1238 __ push(Immediate(var->name())); 1237 __ push(Immediate(var->name()));
1239 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1238 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1240 __ bind(&done); 1239 __ bind(&done);
1241 1240
1242 context()->Plug(eax); 1241 context()->Plug(eax);
1243 1242
1244 } else if (slot != NULL) { 1243 } else {
1245 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1244 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1246 ? "Context slot" 1245 ? "Context slot"
1247 : "Stack slot"); 1246 : "Stack slot");
1248 if (var->mode() == Variable::CONST) { 1247 if (var->mode() == Variable::CONST) {
1249 // Constants may be the hole value if they have not been initialized. 1248 // Constants may be the hole value if they have not been initialized.
1250 // Unhole them. 1249 // Unhole them.
1251 Label done; 1250 Label done;
1252 MemOperand slot_operand = EmitSlotSearch(slot, eax); 1251 MemOperand slot_operand = EmitSlotSearch(slot, eax);
1253 __ mov(eax, slot_operand); 1252 __ mov(eax, slot_operand);
1254 __ cmp(eax, isolate()->factory()->the_hole_value()); 1253 __ cmp(eax, isolate()->factory()->the_hole_value());
1255 __ j(not_equal, &done, Label::kNear); 1254 __ j(not_equal, &done, Label::kNear);
1256 __ mov(eax, isolate()->factory()->undefined_value()); 1255 __ mov(eax, isolate()->factory()->undefined_value());
1257 __ bind(&done); 1256 __ bind(&done);
1258 context()->Plug(eax); 1257 context()->Plug(eax);
1259 } else { 1258 } else {
1260 context()->Plug(slot); 1259 context()->Plug(slot);
1261 } 1260 }
1262
1263 } else {
1264 Comment cmnt(masm_, "Rewritten parameter");
1265 ASSERT_NOT_NULL(property);
1266 // Rewritten parameter accesses are of the form "slot[literal]".
1267
1268 // Assert that the object is in a slot.
1269 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1270 ASSERT_NOT_NULL(object_var);
1271 Slot* object_slot = object_var->AsSlot();
1272 ASSERT_NOT_NULL(object_slot);
1273
1274 // Load the object.
1275 MemOperand object_loc = EmitSlotSearch(object_slot, eax);
1276 __ mov(edx, object_loc);
1277
1278 // Assert that the key is a smi.
1279 Literal* key_literal = property->key()->AsLiteral();
1280 ASSERT_NOT_NULL(key_literal);
1281 ASSERT(key_literal->handle()->IsSmi());
1282
1283 // Load the key.
1284 __ SafeSet(eax, Immediate(key_literal->handle()));
1285
1286 // Do a keyed property load.
1287 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1288 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
1289
1290 // Drop key and object left on the stack by IC.
1291 context()->Plug(eax);
1292 } 1261 }
1293 } 1262 }
1294 1263
1295 1264
1296 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1265 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1297 Comment cmnt(masm_, "[ RegExpLiteral"); 1266 Comment cmnt(masm_, "[ RegExpLiteral");
1298 Label materialized; 1267 Label materialized;
1299 // Registers will be used as follows: 1268 // Registers will be used as follows:
1300 // edi = JS function. 1269 // edi = JS function.
1301 // ecx = literals array. 1270 // ecx = literals array.
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1514 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1483 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1515 Comment cmnt(masm_, "[ Assignment"); 1484 Comment cmnt(masm_, "[ Assignment");
1516 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1485 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1517 // on the left-hand side. 1486 // on the left-hand side.
1518 if (!expr->target()->IsValidLeftHandSide()) { 1487 if (!expr->target()->IsValidLeftHandSide()) {
1519 VisitForEffect(expr->target()); 1488 VisitForEffect(expr->target());
1520 return; 1489 return;
1521 } 1490 }
1522 1491
1523 // Left-hand side can only be a property, a global or a (parameter or local) 1492 // Left-hand side can only be a property, a global or a (parameter or local)
1524 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1493 // slot.
1525 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1494 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1526 LhsKind assign_type = VARIABLE; 1495 LhsKind assign_type = VARIABLE;
1527 Property* property = expr->target()->AsProperty(); 1496 Property* property = expr->target()->AsProperty();
1528 if (property != NULL) { 1497 if (property != NULL) {
1529 assign_type = (property->key()->IsPropertyName()) 1498 assign_type = (property->key()->IsPropertyName())
1530 ? NAMED_PROPERTY 1499 ? NAMED_PROPERTY
1531 : KEYED_PROPERTY; 1500 : KEYED_PROPERTY;
1532 } 1501 }
1533 1502
1534 // Evaluate LHS expression. 1503 // Evaluate LHS expression.
1535 switch (assign_type) { 1504 switch (assign_type) {
1536 case VARIABLE: 1505 case VARIABLE:
1537 // Nothing to do here. 1506 // Nothing to do here.
1538 break; 1507 break;
1539 case NAMED_PROPERTY: 1508 case NAMED_PROPERTY:
1540 if (expr->is_compound()) { 1509 if (expr->is_compound()) {
1541 // We need the receiver both on the stack and in the accumulator. 1510 // We need the receiver both on the stack and in the accumulator.
1542 VisitForAccumulatorValue(property->obj()); 1511 VisitForAccumulatorValue(property->obj());
1543 __ push(result_register()); 1512 __ push(result_register());
1544 } else { 1513 } else {
1545 VisitForStackValue(property->obj()); 1514 VisitForStackValue(property->obj());
1546 } 1515 }
1547 break; 1516 break;
1548 case KEYED_PROPERTY: { 1517 case KEYED_PROPERTY: {
1549 if (expr->is_compound()) { 1518 if (expr->is_compound()) {
1550 if (property->is_arguments_access()) { 1519 VisitForStackValue(property->obj());
1551 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1520 VisitForAccumulatorValue(property->key());
1552 MemOperand slot_operand =
1553 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1554 __ push(slot_operand);
1555 __ SafeSet(eax, Immediate(property->key()->AsLiteral()->handle()));
1556 } else {
1557 VisitForStackValue(property->obj());
1558 VisitForAccumulatorValue(property->key());
1559 }
1560 __ mov(edx, Operand(esp, 0)); 1521 __ mov(edx, Operand(esp, 0));
1561 __ push(eax); 1522 __ push(eax);
1562 } else { 1523 } else {
1563 if (property->is_arguments_access()) { 1524 VisitForStackValue(property->obj());
1564 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1525 VisitForStackValue(property->key());
1565 MemOperand slot_operand =
1566 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1567 __ push(slot_operand);
1568 __ SafePush(Immediate(property->key()->AsLiteral()->handle()));
1569 } else {
1570 VisitForStackValue(property->obj());
1571 VisitForStackValue(property->key());
1572 }
1573 } 1526 }
1574 break; 1527 break;
1575 } 1528 }
1576 } 1529 }
1577 1530
1578 // For compound assignments we need another deoptimization point after the 1531 // For compound assignments we need another deoptimization point after the
1579 // variable/property load. 1532 // variable/property load.
1580 if (expr->is_compound()) { 1533 if (expr->is_compound()) {
1581 { AccumulatorValueContext context(this); 1534 { AccumulatorValueContext context(this);
1582 switch (assign_type) { 1535 switch (assign_type) {
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1766 1719
1767 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { 1720 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1768 // Invalid left-hand sides are rewritten to have a 'throw 1721 // Invalid left-hand sides are rewritten to have a 'throw
1769 // ReferenceError' on the left-hand side. 1722 // ReferenceError' on the left-hand side.
1770 if (!expr->IsValidLeftHandSide()) { 1723 if (!expr->IsValidLeftHandSide()) {
1771 VisitForEffect(expr); 1724 VisitForEffect(expr);
1772 return; 1725 return;
1773 } 1726 }
1774 1727
1775 // Left-hand side can only be a property, a global or a (parameter or local) 1728 // Left-hand side can only be a property, a global or a (parameter or local)
1776 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1729 // slot.
1777 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1730 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1778 LhsKind assign_type = VARIABLE; 1731 LhsKind assign_type = VARIABLE;
1779 Property* prop = expr->AsProperty(); 1732 Property* prop = expr->AsProperty();
1780 if (prop != NULL) { 1733 if (prop != NULL) {
1781 assign_type = (prop->key()->IsPropertyName()) 1734 assign_type = (prop->key()->IsPropertyName())
1782 ? NAMED_PROPERTY 1735 ? NAMED_PROPERTY
1783 : KEYED_PROPERTY; 1736 : KEYED_PROPERTY;
1784 } 1737 }
1785 1738
1786 switch (assign_type) { 1739 switch (assign_type) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1826 break; 1779 break;
1827 } 1780 }
1828 } 1781 }
1829 PrepareForBailoutForId(bailout_ast_id, TOS_REG); 1782 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1830 context()->Plug(eax); 1783 context()->Plug(eax);
1831 } 1784 }
1832 1785
1833 1786
1834 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1787 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1835 Token::Value op) { 1788 Token::Value op) {
1836 // Left-hand sides that rewrite to explicit property accesses do not reach
1837 // here.
1838 ASSERT(var != NULL); 1789 ASSERT(var != NULL);
1839 ASSERT(var->is_global() || var->AsSlot() != NULL); 1790 ASSERT(var->is_global() || var->AsSlot() != NULL);
1840 1791
1841 if (var->is_global()) { 1792 if (var->is_global()) {
1842 ASSERT(!var->is_this()); 1793 ASSERT(!var->is_this());
1843 // Assignment to a global variable. Use inline caching for the 1794 // Assignment to a global variable. Use inline caching for the
1844 // assignment. Right-hand-side value is passed in eax, variable name in 1795 // assignment. Right-hand-side value is passed in eax, variable name in
1845 // ecx, and the global object on the stack. 1796 // ecx, and the global object on the stack.
1846 __ mov(ecx, var->name()); 1797 __ mov(ecx, var->name());
1847 __ mov(edx, GlobalObjectOperand()); 1798 __ mov(edx, GlobalObjectOperand());
(...skipping 1932 matching lines...) Expand 10 before | Expand all | Expand 10 after
3780 SetSourcePosition(expr->position()); 3731 SetSourcePosition(expr->position());
3781 3732
3782 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 3733 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
3783 // as the left-hand side. 3734 // as the left-hand side.
3784 if (!expr->expression()->IsValidLeftHandSide()) { 3735 if (!expr->expression()->IsValidLeftHandSide()) {
3785 VisitForEffect(expr->expression()); 3736 VisitForEffect(expr->expression());
3786 return; 3737 return;
3787 } 3738 }
3788 3739
3789 // Expression can only be a property, a global or a (parameter or local) 3740 // Expression can only be a property, a global or a (parameter or local)
3790 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 3741 // slot.
3791 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 3742 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3792 LhsKind assign_type = VARIABLE; 3743 LhsKind assign_type = VARIABLE;
3793 Property* prop = expr->expression()->AsProperty(); 3744 Property* prop = expr->expression()->AsProperty();
3794 // In case of a property we use the uninitialized expression context 3745 // In case of a property we use the uninitialized expression context
3795 // of the key to detect a named property. 3746 // of the key to detect a named property.
3796 if (prop != NULL) { 3747 if (prop != NULL) {
3797 assign_type = 3748 assign_type =
3798 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 3749 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3799 } 3750 }
3800 3751
3801 // Evaluate expression and get value. 3752 // Evaluate expression and get value.
3802 if (assign_type == VARIABLE) { 3753 if (assign_type == VARIABLE) {
3803 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 3754 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
3804 AccumulatorValueContext context(this); 3755 AccumulatorValueContext context(this);
3805 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); 3756 EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3806 } else { 3757 } else {
3807 // Reserve space for result of postfix operation. 3758 // Reserve space for result of postfix operation.
3808 if (expr->is_postfix() && !context()->IsEffect()) { 3759 if (expr->is_postfix() && !context()->IsEffect()) {
3809 __ push(Immediate(Smi::FromInt(0))); 3760 __ push(Immediate(Smi::FromInt(0)));
3810 } 3761 }
3811 if (assign_type == NAMED_PROPERTY) { 3762 if (assign_type == NAMED_PROPERTY) {
3812 // Put the object both on the stack and in the accumulator. 3763 // Put the object both on the stack and in the accumulator.
3813 VisitForAccumulatorValue(prop->obj()); 3764 VisitForAccumulatorValue(prop->obj());
3814 __ push(eax); 3765 __ push(eax);
3815 EmitNamedPropertyLoad(prop); 3766 EmitNamedPropertyLoad(prop);
3816 } else { 3767 } else {
3817 if (prop->is_arguments_access()) { 3768 VisitForStackValue(prop->obj());
3818 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy(); 3769 VisitForAccumulatorValue(prop->key());
3819 MemOperand slot_operand =
3820 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
3821 __ push(slot_operand);
3822 __ SafeSet(eax, Immediate(prop->key()->AsLiteral()->handle()));
3823 } else {
3824 VisitForStackValue(prop->obj());
3825 VisitForAccumulatorValue(prop->key());
3826 }
3827 __ mov(edx, Operand(esp, 0)); 3770 __ mov(edx, Operand(esp, 0));
3828 __ push(eax); 3771 __ push(eax);
3829 EmitKeyedPropertyLoad(prop); 3772 EmitKeyedPropertyLoad(prop);
3830 } 3773 }
3831 } 3774 }
3832 3775
3833 // We need a second deoptimization point after loading the value 3776 // We need a second deoptimization point after loading the value
3834 // in case evaluating the property load my have a side effect. 3777 // in case evaluating the property load my have a side effect.
3835 if (assign_type == VARIABLE) { 3778 if (assign_type == VARIABLE) {
3836 PrepareForBailout(expr->expression(), TOS_REG); 3779 PrepareForBailout(expr->expression(), TOS_REG);
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
4328 // And return. 4271 // And return.
4329 __ ret(0); 4272 __ ret(0);
4330 } 4273 }
4331 4274
4332 4275
4333 #undef __ 4276 #undef __
4334 4277
4335 } } // namespace v8::internal 4278 } } // namespace v8::internal
4336 4279
4337 #endif // V8_TARGET_ARCH_IA32 4280 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698