| OLD | NEW |
| 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 Loading... |
| 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 966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); | 1208 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); |
| 1215 __ jmp(done); | 1209 __ jmp(done); |
| 1216 } | 1210 } |
| 1217 } | 1211 } |
| 1218 } | 1212 } |
| 1219 } | 1213 } |
| 1220 } | 1214 } |
| 1221 | 1215 |
| 1222 | 1216 |
| 1223 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1217 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
| 1224 // Four cases: non-this global variables, lookup slots, all other | 1218 // Three cases: non-this global variables, lookup slots, and all other |
| 1225 // types of slots, and parameters that rewrite to explicit property | 1219 // types of slots. |
| 1226 // accesses on the arguments object. | |
| 1227 Slot* slot = var->AsSlot(); | 1220 Slot* slot = var->AsSlot(); |
| 1228 Property* property = var->AsProperty(); | 1221 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); |
| 1229 | 1222 |
| 1230 if (var->is_global() && !var->is_this()) { | 1223 if (slot == NULL) { |
| 1231 Comment cmnt(masm_, "Global variable"); | 1224 Comment cmnt(masm_, "Global variable"); |
| 1232 // Use inline caching. Variable name is passed in rcx and the global | 1225 // Use inline caching. Variable name is passed in rcx and the global |
| 1233 // object on the stack. | 1226 // object on the stack. |
| 1234 __ Move(rcx, var->name()); | 1227 __ Move(rcx, var->name()); |
| 1235 __ movq(rax, GlobalObjectOperand()); | 1228 __ movq(rax, GlobalObjectOperand()); |
| 1236 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1229 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 1237 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); | 1230 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); |
| 1238 context()->Plug(rax); | 1231 context()->Plug(rax); |
| 1239 | 1232 |
| 1240 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1233 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 1241 Label done, slow; | 1234 Label done, slow; |
| 1242 | 1235 |
| 1243 // Generate code for loading from variables potentially shadowed | 1236 // Generate code for loading from variables potentially shadowed |
| 1244 // by eval-introduced variables. | 1237 // by eval-introduced variables. |
| 1245 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1238 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
| 1246 | 1239 |
| 1247 __ bind(&slow); | 1240 __ bind(&slow); |
| 1248 Comment cmnt(masm_, "Lookup slot"); | 1241 Comment cmnt(masm_, "Lookup slot"); |
| 1249 __ push(rsi); // Context. | 1242 __ push(rsi); // Context. |
| 1250 __ Push(var->name()); | 1243 __ Push(var->name()); |
| 1251 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1244 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 1252 __ bind(&done); | 1245 __ bind(&done); |
| 1253 | 1246 |
| 1254 context()->Plug(rax); | 1247 context()->Plug(rax); |
| 1255 | 1248 |
| 1256 } else if (slot != NULL) { | 1249 } else { |
| 1257 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) | 1250 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) |
| 1258 ? "Context slot" | 1251 ? "Context slot" |
| 1259 : "Stack slot"); | 1252 : "Stack slot"); |
| 1260 if (var->mode() == Variable::CONST) { | 1253 if (var->mode() == Variable::CONST) { |
| 1261 // Constants may be the hole value if they have not been initialized. | 1254 // Constants may be the hole value if they have not been initialized. |
| 1262 // Unhole them. | 1255 // Unhole them. |
| 1263 Label done; | 1256 Label done; |
| 1264 MemOperand slot_operand = EmitSlotSearch(slot, rax); | 1257 MemOperand slot_operand = EmitSlotSearch(slot, rax); |
| 1265 __ movq(rax, slot_operand); | 1258 __ movq(rax, slot_operand); |
| 1266 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 1259 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
| 1267 __ j(not_equal, &done, Label::kNear); | 1260 __ j(not_equal, &done, Label::kNear); |
| 1268 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1261 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1269 __ bind(&done); | 1262 __ bind(&done); |
| 1270 context()->Plug(rax); | 1263 context()->Plug(rax); |
| 1271 } else { | 1264 } else { |
| 1272 context()->Plug(slot); | 1265 context()->Plug(slot); |
| 1273 } | 1266 } |
| 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 } | 1267 } |
| 1303 } | 1268 } |
| 1304 | 1269 |
| 1305 | 1270 |
| 1306 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1271 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1307 Comment cmnt(masm_, "[ RegExpLiteral"); | 1272 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 1308 Label materialized; | 1273 Label materialized; |
| 1309 // Registers will be used as follows: | 1274 // Registers will be used as follows: |
| 1310 // rdi = JS function. | 1275 // rdi = JS function. |
| 1311 // rcx = literals array. | 1276 // rcx = literals array. |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1524 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1489 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
| 1525 Comment cmnt(masm_, "[ Assignment"); | 1490 Comment cmnt(masm_, "[ Assignment"); |
| 1526 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 1491 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
| 1527 // on the left-hand side. | 1492 // on the left-hand side. |
| 1528 if (!expr->target()->IsValidLeftHandSide()) { | 1493 if (!expr->target()->IsValidLeftHandSide()) { |
| 1529 VisitForEffect(expr->target()); | 1494 VisitForEffect(expr->target()); |
| 1530 return; | 1495 return; |
| 1531 } | 1496 } |
| 1532 | 1497 |
| 1533 // Left-hand side can only be a property, a global or a (parameter or local) | 1498 // 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. | 1499 // slot. |
| 1535 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1500 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1536 LhsKind assign_type = VARIABLE; | 1501 LhsKind assign_type = VARIABLE; |
| 1537 Property* property = expr->target()->AsProperty(); | 1502 Property* property = expr->target()->AsProperty(); |
| 1538 if (property != NULL) { | 1503 if (property != NULL) { |
| 1539 assign_type = (property->key()->IsPropertyName()) | 1504 assign_type = (property->key()->IsPropertyName()) |
| 1540 ? NAMED_PROPERTY | 1505 ? NAMED_PROPERTY |
| 1541 : KEYED_PROPERTY; | 1506 : KEYED_PROPERTY; |
| 1542 } | 1507 } |
| 1543 | 1508 |
| 1544 // Evaluate LHS expression. | 1509 // Evaluate LHS expression. |
| 1545 switch (assign_type) { | 1510 switch (assign_type) { |
| 1546 case VARIABLE: | 1511 case VARIABLE: |
| 1547 // Nothing to do here. | 1512 // Nothing to do here. |
| 1548 break; | 1513 break; |
| 1549 case NAMED_PROPERTY: | 1514 case NAMED_PROPERTY: |
| 1550 if (expr->is_compound()) { | 1515 if (expr->is_compound()) { |
| 1551 // We need the receiver both on the stack and in the accumulator. | 1516 // We need the receiver both on the stack and in the accumulator. |
| 1552 VisitForAccumulatorValue(property->obj()); | 1517 VisitForAccumulatorValue(property->obj()); |
| 1553 __ push(result_register()); | 1518 __ push(result_register()); |
| 1554 } else { | 1519 } else { |
| 1555 VisitForStackValue(property->obj()); | 1520 VisitForStackValue(property->obj()); |
| 1556 } | 1521 } |
| 1557 break; | 1522 break; |
| 1558 case KEYED_PROPERTY: { | 1523 case KEYED_PROPERTY: { |
| 1559 if (expr->is_compound()) { | 1524 if (expr->is_compound()) { |
| 1560 if (property->is_arguments_access()) { | 1525 VisitForStackValue(property->obj()); |
| 1561 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 1526 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)); | 1527 __ movq(rdx, Operand(rsp, 0)); |
| 1571 __ push(rax); | 1528 __ push(rax); |
| 1572 } else { | 1529 } else { |
| 1573 if (property->is_arguments_access()) { | 1530 VisitForStackValue(property->obj()); |
| 1574 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 1531 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 } | 1532 } |
| 1584 break; | 1533 break; |
| 1585 } | 1534 } |
| 1586 } | 1535 } |
| 1587 | 1536 |
| 1588 // For compound assignments we need another deoptimization point after the | 1537 // For compound assignments we need another deoptimization point after the |
| 1589 // variable/property load. | 1538 // variable/property load. |
| 1590 if (expr->is_compound()) { | 1539 if (expr->is_compound()) { |
| 1591 { AccumulatorValueContext context(this); | 1540 { AccumulatorValueContext context(this); |
| 1592 switch (assign_type) { | 1541 switch (assign_type) { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1739 | 1688 |
| 1740 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1689 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
| 1741 // Invalid left-hand sides are rewritten to have a 'throw | 1690 // Invalid left-hand sides are rewritten to have a 'throw |
| 1742 // ReferenceError' on the left-hand side. | 1691 // ReferenceError' on the left-hand side. |
| 1743 if (!expr->IsValidLeftHandSide()) { | 1692 if (!expr->IsValidLeftHandSide()) { |
| 1744 VisitForEffect(expr); | 1693 VisitForEffect(expr); |
| 1745 return; | 1694 return; |
| 1746 } | 1695 } |
| 1747 | 1696 |
| 1748 // Left-hand side can only be a property, a global or a (parameter or local) | 1697 // 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. | 1698 // slot. |
| 1750 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1699 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1751 LhsKind assign_type = VARIABLE; | 1700 LhsKind assign_type = VARIABLE; |
| 1752 Property* prop = expr->AsProperty(); | 1701 Property* prop = expr->AsProperty(); |
| 1753 if (prop != NULL) { | 1702 if (prop != NULL) { |
| 1754 assign_type = (prop->key()->IsPropertyName()) | 1703 assign_type = (prop->key()->IsPropertyName()) |
| 1755 ? NAMED_PROPERTY | 1704 ? NAMED_PROPERTY |
| 1756 : KEYED_PROPERTY; | 1705 : KEYED_PROPERTY; |
| 1757 } | 1706 } |
| 1758 | 1707 |
| 1759 switch (assign_type) { | 1708 switch (assign_type) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1770 __ pop(rax); // Restore value. | 1719 __ pop(rax); // Restore value. |
| 1771 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1720 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
| 1772 Handle<Code> ic = is_strict_mode() | 1721 Handle<Code> ic = is_strict_mode() |
| 1773 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1722 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1774 : isolate()->builtins()->StoreIC_Initialize(); | 1723 : isolate()->builtins()->StoreIC_Initialize(); |
| 1775 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1724 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); |
| 1776 break; | 1725 break; |
| 1777 } | 1726 } |
| 1778 case KEYED_PROPERTY: { | 1727 case KEYED_PROPERTY: { |
| 1779 __ push(rax); // Preserve value. | 1728 __ push(rax); // Preserve value. |
| 1780 if (prop->is_synthetic()) { | 1729 VisitForStackValue(prop->obj()); |
| 1781 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 1730 VisitForAccumulatorValue(prop->key()); |
| 1782 ASSERT(prop->key()->AsLiteral() != NULL); | 1731 __ movq(rcx, rax); |
| 1783 { AccumulatorValueContext for_object(this); | 1732 __ 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. | 1733 __ pop(rax); // Restore value. |
| 1795 Handle<Code> ic = is_strict_mode() | 1734 Handle<Code> ic = is_strict_mode() |
| 1796 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1735 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 1797 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1736 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 1798 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1737 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); |
| 1799 break; | 1738 break; |
| 1800 } | 1739 } |
| 1801 } | 1740 } |
| 1802 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1741 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
| 1803 context()->Plug(rax); | 1742 context()->Plug(rax); |
| 1804 } | 1743 } |
| 1805 | 1744 |
| 1806 | 1745 |
| 1807 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1746 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1808 Token::Value op) { | 1747 Token::Value op) { |
| 1809 // Left-hand sides that rewrite to explicit property accesses do not reach | |
| 1810 // here. | |
| 1811 ASSERT(var != NULL); | 1748 ASSERT(var != NULL); |
| 1812 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1749 ASSERT(var->is_global() || var->AsSlot() != NULL); |
| 1813 | 1750 |
| 1814 if (var->is_global()) { | 1751 if (var->is_global()) { |
| 1815 ASSERT(!var->is_this()); | 1752 ASSERT(!var->is_this()); |
| 1816 // Assignment to a global variable. Use inline caching for the | 1753 // Assignment to a global variable. Use inline caching for the |
| 1817 // assignment. Right-hand-side value is passed in rax, variable name in | 1754 // assignment. Right-hand-side value is passed in rax, variable name in |
| 1818 // rcx, and the global object on the stack. | 1755 // rcx, and the global object on the stack. |
| 1819 __ Move(rcx, var->name()); | 1756 __ Move(rcx, var->name()); |
| 1820 __ movq(rdx, GlobalObjectOperand()); | 1757 __ movq(rdx, GlobalObjectOperand()); |
| (...skipping 1934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3755 SetSourcePosition(expr->position()); | 3692 SetSourcePosition(expr->position()); |
| 3756 | 3693 |
| 3757 // Invalid left-hand-sides are rewritten to have a 'throw | 3694 // Invalid left-hand-sides are rewritten to have a 'throw |
| 3758 // ReferenceError' as the left-hand side. | 3695 // ReferenceError' as the left-hand side. |
| 3759 if (!expr->expression()->IsValidLeftHandSide()) { | 3696 if (!expr->expression()->IsValidLeftHandSide()) { |
| 3760 VisitForEffect(expr->expression()); | 3697 VisitForEffect(expr->expression()); |
| 3761 return; | 3698 return; |
| 3762 } | 3699 } |
| 3763 | 3700 |
| 3764 // Expression can only be a property, a global or a (parameter or local) | 3701 // 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. | 3702 // slot. |
| 3766 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 3703 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 3767 LhsKind assign_type = VARIABLE; | 3704 LhsKind assign_type = VARIABLE; |
| 3768 Property* prop = expr->expression()->AsProperty(); | 3705 Property* prop = expr->expression()->AsProperty(); |
| 3769 // In case of a property we use the uninitialized expression context | 3706 // In case of a property we use the uninitialized expression context |
| 3770 // of the key to detect a named property. | 3707 // of the key to detect a named property. |
| 3771 if (prop != NULL) { | 3708 if (prop != NULL) { |
| 3772 assign_type = | 3709 assign_type = |
| 3773 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 3710 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
| 3774 } | 3711 } |
| 3775 | 3712 |
| 3776 // Evaluate expression and get value. | 3713 // Evaluate expression and get value. |
| 3777 if (assign_type == VARIABLE) { | 3714 if (assign_type == VARIABLE) { |
| 3778 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 3715 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
| 3779 AccumulatorValueContext context(this); | 3716 AccumulatorValueContext context(this); |
| 3780 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); | 3717 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); |
| 3781 } else { | 3718 } else { |
| 3782 // Reserve space for result of postfix operation. | 3719 // Reserve space for result of postfix operation. |
| 3783 if (expr->is_postfix() && !context()->IsEffect()) { | 3720 if (expr->is_postfix() && !context()->IsEffect()) { |
| 3784 __ Push(Smi::FromInt(0)); | 3721 __ Push(Smi::FromInt(0)); |
| 3785 } | 3722 } |
| 3786 if (assign_type == NAMED_PROPERTY) { | 3723 if (assign_type == NAMED_PROPERTY) { |
| 3787 VisitForAccumulatorValue(prop->obj()); | 3724 VisitForAccumulatorValue(prop->obj()); |
| 3788 __ push(rax); // Copy of receiver, needed for later store. | 3725 __ push(rax); // Copy of receiver, needed for later store. |
| 3789 EmitNamedPropertyLoad(prop); | 3726 EmitNamedPropertyLoad(prop); |
| 3790 } else { | 3727 } else { |
| 3791 if (prop->is_arguments_access()) { | 3728 VisitForStackValue(prop->obj()); |
| 3792 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy(); | 3729 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 | 3730 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack |
| 3802 __ push(rax); // Copy of key, needed for later store. | 3731 __ push(rax); // Copy of key, needed for later store. |
| 3803 EmitKeyedPropertyLoad(prop); | 3732 EmitKeyedPropertyLoad(prop); |
| 3804 } | 3733 } |
| 3805 } | 3734 } |
| 3806 | 3735 |
| 3807 // We need a second deoptimization point after loading the value | 3736 // We need a second deoptimization point after loading the value |
| 3808 // in case evaluating the property load my have a side effect. | 3737 // in case evaluating the property load my have a side effect. |
| 3809 if (assign_type == VARIABLE) { | 3738 if (assign_type == VARIABLE) { |
| 3810 PrepareForBailout(expr->expression(), TOS_REG); | 3739 PrepareForBailout(expr->expression(), TOS_REG); |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4309 __ ret(0); | 4238 __ ret(0); |
| 4310 } | 4239 } |
| 4311 | 4240 |
| 4312 | 4241 |
| 4313 #undef __ | 4242 #undef __ |
| 4314 | 4243 |
| 4315 | 4244 |
| 4316 } } // namespace v8::internal | 4245 } } // namespace v8::internal |
| 4317 | 4246 |
| 4318 #endif // V8_TARGET_ARCH_X64 | 4247 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |