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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1202 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); | 1203 EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); |
1203 __ jmp(done); | 1204 __ jmp(done); |
1204 } | 1205 } |
1205 } | 1206 } |
1206 } | 1207 } |
1207 } | 1208 } |
1208 } | 1209 } |
1209 | 1210 |
1210 | 1211 |
1211 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1212 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
1212 // Four cases: non-this global variables, lookup slots, all other | 1213 // Three cases: non-this global variables, lookup slots, and all other |
1213 // types of slots, and parameters that rewrite to explicit property | 1214 // types of slots. |
1214 // accesses on the arguments object. | |
1215 Slot* slot = var->AsSlot(); | 1215 Slot* slot = var->AsSlot(); |
1216 Property* property = var->AsProperty(); | 1216 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); |
1217 | 1217 |
1218 if (var->is_global() && !var->is_this()) { | 1218 if (slot == NULL) { |
1219 Comment cmnt(masm_, "Global variable"); | 1219 Comment cmnt(masm_, "Global variable"); |
1220 // 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 |
1221 // object on the stack. | 1221 // object on the stack. |
1222 __ mov(eax, GlobalObjectOperand()); | 1222 __ mov(eax, GlobalObjectOperand()); |
1223 __ mov(ecx, var->name()); | 1223 __ mov(ecx, var->name()); |
1224 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1224 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1225 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); | 1225 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); |
1226 context()->Plug(eax); | 1226 context()->Plug(eax); |
1227 | 1227 |
1228 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1228 } else if (slot->type() == Slot::LOOKUP) { |
1229 Label done, slow; | 1229 Label done, slow; |
1230 | 1230 |
1231 // Generate code for loading from variables potentially shadowed | 1231 // Generate code for loading from variables potentially shadowed |
1232 // by eval-introduced variables. | 1232 // by eval-introduced variables. |
1233 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1233 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
1234 | 1234 |
1235 __ bind(&slow); | 1235 __ bind(&slow); |
1236 Comment cmnt(masm_, "Lookup slot"); | 1236 Comment cmnt(masm_, "Lookup slot"); |
1237 __ push(esi); // Context. | 1237 __ push(esi); // Context. |
1238 __ push(Immediate(var->name())); | 1238 __ push(Immediate(var->name())); |
1239 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1239 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
1240 __ bind(&done); | 1240 __ bind(&done); |
1241 | 1241 |
1242 context()->Plug(eax); | 1242 context()->Plug(eax); |
1243 | 1243 |
1244 } else if (slot != NULL) { | 1244 } else { |
1245 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) | 1245 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) |
1246 ? "Context slot" | 1246 ? "Context slot" |
1247 : "Stack slot"); | 1247 : "Stack slot"); |
1248 if (var->mode() == Variable::CONST) { | 1248 if (var->mode() == Variable::CONST) { |
1249 // 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. |
1250 // Unhole them. | 1250 // Unhole them. |
1251 Label done; | 1251 Label done; |
1252 MemOperand slot_operand = EmitSlotSearch(slot, eax); | 1252 MemOperand slot_operand = EmitSlotSearch(slot, eax); |
1253 __ mov(eax, slot_operand); | 1253 __ mov(eax, slot_operand); |
1254 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1254 __ cmp(eax, isolate()->factory()->the_hole_value()); |
1255 __ j(not_equal, &done, Label::kNear); | 1255 __ j(not_equal, &done, Label::kNear); |
1256 __ mov(eax, isolate()->factory()->undefined_value()); | 1256 __ mov(eax, isolate()->factory()->undefined_value()); |
1257 __ bind(&done); | 1257 __ bind(&done); |
1258 context()->Plug(eax); | 1258 context()->Plug(eax); |
1259 } else { | 1259 } else { |
1260 context()->Plug(slot); | 1260 context()->Plug(slot); |
1261 } | 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); | |
1292 } | 1262 } |
1293 } | 1263 } |
1294 | 1264 |
1295 | 1265 |
1296 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1266 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1297 Comment cmnt(masm_, "[ RegExpLiteral"); | 1267 Comment cmnt(masm_, "[ RegExpLiteral"); |
1298 Label materialized; | 1268 Label materialized; |
1299 // Registers will be used as follows: | 1269 // Registers will be used as follows: |
1300 // edi = JS function. | 1270 // edi = JS function. |
1301 // ecx = literals array. | 1271 // ecx = literals array. |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 void FullCodeGenerator::VisitAssignment(Assignment* expr) { | 1484 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
1515 Comment cmnt(masm_, "[ Assignment"); | 1485 Comment cmnt(masm_, "[ Assignment"); |
1516 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 1486 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
1517 // on the left-hand side. | 1487 // on the left-hand side. |
1518 if (!expr->target()->IsValidLeftHandSide()) { | 1488 if (!expr->target()->IsValidLeftHandSide()) { |
1519 VisitForEffect(expr->target()); | 1489 VisitForEffect(expr->target()); |
1520 return; | 1490 return; |
1521 } | 1491 } |
1522 | 1492 |
1523 // Left-hand side can only be a property, a global or a (parameter or local) | 1493 // 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. | 1494 // slot. |
1525 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1495 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1526 LhsKind assign_type = VARIABLE; | 1496 LhsKind assign_type = VARIABLE; |
1527 Property* property = expr->target()->AsProperty(); | 1497 Property* property = expr->target()->AsProperty(); |
1528 if (property != NULL) { | 1498 if (property != NULL) { |
1529 assign_type = (property->key()->IsPropertyName()) | 1499 assign_type = (property->key()->IsPropertyName()) |
1530 ? NAMED_PROPERTY | 1500 ? NAMED_PROPERTY |
1531 : KEYED_PROPERTY; | 1501 : KEYED_PROPERTY; |
1532 } | 1502 } |
1533 | 1503 |
1534 // Evaluate LHS expression. | 1504 // Evaluate LHS expression. |
1535 switch (assign_type) { | 1505 switch (assign_type) { |
1536 case VARIABLE: | 1506 case VARIABLE: |
1537 // Nothing to do here. | 1507 // Nothing to do here. |
1538 break; | 1508 break; |
1539 case NAMED_PROPERTY: | 1509 case NAMED_PROPERTY: |
1540 if (expr->is_compound()) { | 1510 if (expr->is_compound()) { |
1541 // We need the receiver both on the stack and in the accumulator. | 1511 // We need the receiver both on the stack and in the accumulator. |
1542 VisitForAccumulatorValue(property->obj()); | 1512 VisitForAccumulatorValue(property->obj()); |
1543 __ push(result_register()); | 1513 __ push(result_register()); |
1544 } else { | 1514 } else { |
1545 VisitForStackValue(property->obj()); | 1515 VisitForStackValue(property->obj()); |
1546 } | 1516 } |
1547 break; | 1517 break; |
1548 case KEYED_PROPERTY: { | 1518 case KEYED_PROPERTY: { |
1549 if (expr->is_compound()) { | 1519 if (expr->is_compound()) { |
1550 if (property->is_arguments_access()) { | 1520 VisitForStackValue(property->obj()); |
1551 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 1521 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)); | 1522 __ mov(edx, Operand(esp, 0)); |
1561 __ push(eax); | 1523 __ push(eax); |
1562 } else { | 1524 } else { |
1563 if (property->is_arguments_access()) { | 1525 VisitForStackValue(property->obj()); |
1564 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 1526 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 } | 1527 } |
1574 break; | 1528 break; |
1575 } | 1529 } |
1576 } | 1530 } |
1577 | 1531 |
1578 // For compound assignments we need another deoptimization point after the | 1532 // For compound assignments we need another deoptimization point after the |
1579 // variable/property load. | 1533 // variable/property load. |
1580 if (expr->is_compound()) { | 1534 if (expr->is_compound()) { |
1581 { AccumulatorValueContext context(this); | 1535 { AccumulatorValueContext context(this); |
1582 switch (assign_type) { | 1536 switch (assign_type) { |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 | 1720 |
1767 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1721 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
1768 // Invalid left-hand sides are rewritten to have a 'throw | 1722 // Invalid left-hand sides are rewritten to have a 'throw |
1769 // ReferenceError' on the left-hand side. | 1723 // ReferenceError' on the left-hand side. |
1770 if (!expr->IsValidLeftHandSide()) { | 1724 if (!expr->IsValidLeftHandSide()) { |
1771 VisitForEffect(expr); | 1725 VisitForEffect(expr); |
1772 return; | 1726 return; |
1773 } | 1727 } |
1774 | 1728 |
1775 // Left-hand side can only be a property, a global or a (parameter or local) | 1729 // 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. | 1730 // slot. |
1777 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1731 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1778 LhsKind assign_type = VARIABLE; | 1732 LhsKind assign_type = VARIABLE; |
1779 Property* prop = expr->AsProperty(); | 1733 Property* prop = expr->AsProperty(); |
1780 if (prop != NULL) { | 1734 if (prop != NULL) { |
1781 assign_type = (prop->key()->IsPropertyName()) | 1735 assign_type = (prop->key()->IsPropertyName()) |
1782 ? NAMED_PROPERTY | 1736 ? NAMED_PROPERTY |
1783 : KEYED_PROPERTY; | 1737 : KEYED_PROPERTY; |
1784 } | 1738 } |
1785 | 1739 |
1786 switch (assign_type) { | 1740 switch (assign_type) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 break; | 1780 break; |
1827 } | 1781 } |
1828 } | 1782 } |
1829 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1783 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1830 context()->Plug(eax); | 1784 context()->Plug(eax); |
1831 } | 1785 } |
1832 | 1786 |
1833 | 1787 |
1834 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1788 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1835 Token::Value op) { | 1789 Token::Value op) { |
1836 // Left-hand sides that rewrite to explicit property accesses do not reach | |
1837 // here. | |
1838 ASSERT(var != NULL); | 1790 ASSERT(var != NULL); |
1839 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1791 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1840 | 1792 |
1841 if (var->is_global()) { | 1793 if (var->is_global()) { |
1842 ASSERT(!var->is_this()); | 1794 ASSERT(!var->is_this()); |
1843 // Assignment to a global variable. Use inline caching for the | 1795 // Assignment to a global variable. Use inline caching for the |
1844 // assignment. Right-hand-side value is passed in eax, variable name in | 1796 // assignment. Right-hand-side value is passed in eax, variable name in |
1845 // ecx, and the global object on the stack. | 1797 // ecx, and the global object on the stack. |
1846 __ mov(ecx, var->name()); | 1798 __ mov(ecx, var->name()); |
1847 __ mov(edx, GlobalObjectOperand()); | 1799 __ mov(edx, GlobalObjectOperand()); |
(...skipping 1932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3780 SetSourcePosition(expr->position()); | 3732 SetSourcePosition(expr->position()); |
3781 | 3733 |
3782 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 3734 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
3783 // as the left-hand side. | 3735 // as the left-hand side. |
3784 if (!expr->expression()->IsValidLeftHandSide()) { | 3736 if (!expr->expression()->IsValidLeftHandSide()) { |
3785 VisitForEffect(expr->expression()); | 3737 VisitForEffect(expr->expression()); |
3786 return; | 3738 return; |
3787 } | 3739 } |
3788 | 3740 |
3789 // Expression can only be a property, a global or a (parameter or local) | 3741 // 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. | 3742 // slot. |
3791 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 3743 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
3792 LhsKind assign_type = VARIABLE; | 3744 LhsKind assign_type = VARIABLE; |
3793 Property* prop = expr->expression()->AsProperty(); | 3745 Property* prop = expr->expression()->AsProperty(); |
3794 // In case of a property we use the uninitialized expression context | 3746 // In case of a property we use the uninitialized expression context |
3795 // of the key to detect a named property. | 3747 // of the key to detect a named property. |
3796 if (prop != NULL) { | 3748 if (prop != NULL) { |
3797 assign_type = | 3749 assign_type = |
3798 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; | 3750 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
3799 } | 3751 } |
3800 | 3752 |
3801 // Evaluate expression and get value. | 3753 // Evaluate expression and get value. |
3802 if (assign_type == VARIABLE) { | 3754 if (assign_type == VARIABLE) { |
3803 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 3755 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
3804 AccumulatorValueContext context(this); | 3756 AccumulatorValueContext context(this); |
3805 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); | 3757 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); |
3806 } else { | 3758 } else { |
3807 // Reserve space for result of postfix operation. | 3759 // Reserve space for result of postfix operation. |
3808 if (expr->is_postfix() && !context()->IsEffect()) { | 3760 if (expr->is_postfix() && !context()->IsEffect()) { |
3809 __ push(Immediate(Smi::FromInt(0))); | 3761 __ push(Immediate(Smi::FromInt(0))); |
3810 } | 3762 } |
3811 if (assign_type == NAMED_PROPERTY) { | 3763 if (assign_type == NAMED_PROPERTY) { |
3812 // Put the object both on the stack and in the accumulator. | 3764 // Put the object both on the stack and in the accumulator. |
3813 VisitForAccumulatorValue(prop->obj()); | 3765 VisitForAccumulatorValue(prop->obj()); |
3814 __ push(eax); | 3766 __ push(eax); |
3815 EmitNamedPropertyLoad(prop); | 3767 EmitNamedPropertyLoad(prop); |
3816 } else { | 3768 } else { |
3817 if (prop->is_arguments_access()) { | 3769 VisitForStackValue(prop->obj()); |
3818 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy(); | 3770 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)); | 3771 __ mov(edx, Operand(esp, 0)); |
3828 __ push(eax); | 3772 __ push(eax); |
3829 EmitKeyedPropertyLoad(prop); | 3773 EmitKeyedPropertyLoad(prop); |
3830 } | 3774 } |
3831 } | 3775 } |
3832 | 3776 |
3833 // We need a second deoptimization point after loading the value | 3777 // We need a second deoptimization point after loading the value |
3834 // in case evaluating the property load my have a side effect. | 3778 // in case evaluating the property load my have a side effect. |
3835 if (assign_type == VARIABLE) { | 3779 if (assign_type == VARIABLE) { |
3836 PrepareForBailout(expr->expression(), TOS_REG); | 3780 PrepareForBailout(expr->expression(), TOS_REG); |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4328 // And return. | 4272 // And return. |
4329 __ ret(0); | 4273 __ ret(0); |
4330 } | 4274 } |
4331 | 4275 |
4332 | 4276 |
4333 #undef __ | 4277 #undef __ |
4334 | 4278 |
4335 } } // namespace v8::internal | 4279 } } // namespace v8::internal |
4336 | 4280 |
4337 #endif // V8_TARGET_ARCH_IA32 | 4281 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |