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

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