OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 __ push(r3); // Current entry. | 883 __ push(r3); // Current entry. |
884 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); | 884 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); |
885 __ mov(r3, Operand(r0), SetCC); | 885 __ mov(r3, Operand(r0), SetCC); |
886 __ b(eq, loop_statement.continue_target()); | 886 __ b(eq, loop_statement.continue_target()); |
887 | 887 |
888 // Update the 'each' property or variable from the possibly filtered | 888 // Update the 'each' property or variable from the possibly filtered |
889 // entry in register r3. | 889 // entry in register r3. |
890 __ bind(&update_each); | 890 __ bind(&update_each); |
891 __ mov(result_register(), r3); | 891 __ mov(result_register(), r3); |
892 // Perform the assignment as if via '='. | 892 // Perform the assignment as if via '='. |
893 EmitAssignment(stmt->each()); | 893 { EffectContext context(this); |
| 894 EmitAssignment(stmt->each(), stmt->AssignmentId()); |
| 895 } |
894 | 896 |
895 // Generate code for the body of the loop. | 897 // Generate code for the body of the loop. |
896 Visit(stmt->body()); | 898 Visit(stmt->body()); |
897 | 899 |
898 // Generate code for the going to the next element by incrementing | 900 // Generate code for the going to the next element by incrementing |
899 // the index (smi) stored on top of the stack. | 901 // the index (smi) stored on top of the stack. |
900 __ bind(loop_statement.continue_target()); | 902 __ bind(loop_statement.continue_target()); |
901 __ pop(r0); | 903 __ pop(r0); |
902 __ add(r0, r0, Operand(Smi::FromInt(1))); | 904 __ add(r0, r0, Operand(Smi::FromInt(1))); |
903 __ push(r0); | 905 __ push(r0); |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1437 break; | 1439 break; |
1438 case KEYED_PROPERTY: | 1440 case KEYED_PROPERTY: |
1439 EmitKeyedPropertyLoad(property); | 1441 EmitKeyedPropertyLoad(property); |
1440 break; | 1442 break; |
1441 } | 1443 } |
1442 } | 1444 } |
1443 | 1445 |
1444 // For property compound assignments we need another deoptimization | 1446 // For property compound assignments we need another deoptimization |
1445 // point after the property load. | 1447 // point after the property load. |
1446 if (property != NULL) { | 1448 if (property != NULL) { |
1447 PrepareForBailoutForId(expr->compound_bailout_id(), TOS_REG); | 1449 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); |
1448 } | 1450 } |
1449 | 1451 |
1450 Token::Value op = expr->binary_op(); | 1452 Token::Value op = expr->binary_op(); |
1451 ConstantOperand constant = ShouldInlineSmiCase(op) | 1453 ConstantOperand constant = ShouldInlineSmiCase(op) |
1452 ? GetConstantOperand(op, expr->target(), expr->value()) | 1454 ? GetConstantOperand(op, expr->target(), expr->value()) |
1453 : kNoConstants; | 1455 : kNoConstants; |
1454 ASSERT(constant == kRightConstant || constant == kNoConstants); | 1456 ASSERT(constant == kRightConstant || constant == kNoConstants); |
1455 if (constant == kNoConstants) { | 1457 if (constant == kNoConstants) { |
1456 __ push(r0); // Left operand goes on the stack. | 1458 __ push(r0); // Left operand goes on the stack. |
1457 VisitForAccumulatorValue(expr->value()); | 1459 VisitForAccumulatorValue(expr->value()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1529 | 1531 |
1530 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1532 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1531 OverwriteMode mode) { | 1533 OverwriteMode mode) { |
1532 __ pop(r1); | 1534 __ pop(r1); |
1533 GenericBinaryOpStub stub(op, mode, r1, r0); | 1535 GenericBinaryOpStub stub(op, mode, r1, r0); |
1534 __ CallStub(&stub); | 1536 __ CallStub(&stub); |
1535 context()->Plug(r0); | 1537 context()->Plug(r0); |
1536 } | 1538 } |
1537 | 1539 |
1538 | 1540 |
1539 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1541 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
1540 // Invalid left-hand sides are rewritten to have a 'throw | 1542 // Invalid left-hand sides are rewritten to have a 'throw |
1541 // ReferenceError' on the left-hand side. | 1543 // ReferenceError' on the left-hand side. |
1542 if (!expr->IsValidLeftHandSide()) { | 1544 if (!expr->IsValidLeftHandSide()) { |
1543 VisitForEffect(expr); | 1545 VisitForEffect(expr); |
1544 return; | 1546 return; |
1545 } | 1547 } |
1546 | 1548 |
1547 // Left-hand side can only be a property, a global or a (parameter or local) | 1549 // Left-hand side can only be a property, a global or a (parameter or local) |
1548 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1550 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1549 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1551 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
(...skipping 27 matching lines...) Expand all Loading... |
1577 VisitForStackValue(prop->obj()); | 1579 VisitForStackValue(prop->obj()); |
1578 VisitForAccumulatorValue(prop->key()); | 1580 VisitForAccumulatorValue(prop->key()); |
1579 __ mov(r1, r0); | 1581 __ mov(r1, r0); |
1580 __ pop(r2); | 1582 __ pop(r2); |
1581 __ pop(r0); // Restore value. | 1583 __ pop(r0); // Restore value. |
1582 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1584 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1583 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1585 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1584 break; | 1586 break; |
1585 } | 1587 } |
1586 } | 1588 } |
| 1589 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
| 1590 context()->Plug(r0); |
1587 } | 1591 } |
1588 | 1592 |
1589 | 1593 |
1590 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1594 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1591 Token::Value op) { | 1595 Token::Value op) { |
1592 // Left-hand sides that rewrite to explicit property accesses do not reach | 1596 // Left-hand sides that rewrite to explicit property accesses do not reach |
1593 // here. | 1597 // here. |
1594 ASSERT(var != NULL); | 1598 ASSERT(var != NULL); |
1595 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1599 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1596 | 1600 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1650 if (op == Token::INIT_CONST) { | 1654 if (op == Token::INIT_CONST) { |
1651 // The runtime will ignore const redeclaration. | 1655 // The runtime will ignore const redeclaration. |
1652 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1656 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
1653 } else { | 1657 } else { |
1654 __ CallRuntime(Runtime::kStoreContextSlot, 3); | 1658 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
1655 } | 1659 } |
1656 break; | 1660 break; |
1657 } | 1661 } |
1658 __ bind(&done); | 1662 __ bind(&done); |
1659 } | 1663 } |
1660 | |
1661 context()->Plug(result_register()); | |
1662 } | 1664 } |
1663 | 1665 |
1664 | 1666 |
1665 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1667 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1666 // Assignment to a property, using a named store IC. | 1668 // Assignment to a property, using a named store IC. |
1667 Property* prop = expr->target()->AsProperty(); | 1669 Property* prop = expr->target()->AsProperty(); |
1668 ASSERT(prop != NULL); | 1670 ASSERT(prop != NULL); |
1669 ASSERT(prop->key()->AsLiteral() != NULL); | 1671 ASSERT(prop->key()->AsLiteral() != NULL); |
1670 | 1672 |
1671 // If the assignment starts a block of assignments to the same object, | 1673 // If the assignment starts a block of assignments to the same object, |
(...skipping 22 matching lines...) Expand all Loading... |
1694 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1696 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1695 | 1697 |
1696 // If the assignment ends an initialization block, revert to fast case. | 1698 // If the assignment ends an initialization block, revert to fast case. |
1697 if (expr->ends_initialization_block()) { | 1699 if (expr->ends_initialization_block()) { |
1698 __ push(r0); // Result of assignment, saved even if not needed. | 1700 __ push(r0); // Result of assignment, saved even if not needed. |
1699 // Receiver is under the result value. | 1701 // Receiver is under the result value. |
1700 __ ldr(ip, MemOperand(sp, kPointerSize)); | 1702 __ ldr(ip, MemOperand(sp, kPointerSize)); |
1701 __ push(ip); | 1703 __ push(ip); |
1702 __ CallRuntime(Runtime::kToFastProperties, 1); | 1704 __ CallRuntime(Runtime::kToFastProperties, 1); |
1703 __ pop(r0); | 1705 __ pop(r0); |
1704 context()->DropAndPlug(1, r0); | 1706 __ Drop(1); |
1705 } else { | |
1706 context()->Plug(r0); | |
1707 } | 1707 } |
| 1708 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 1709 context()->Plug(r0); |
1708 } | 1710 } |
1709 | 1711 |
1710 | 1712 |
1711 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1713 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1712 // Assignment to a property, using a keyed store IC. | 1714 // Assignment to a property, using a keyed store IC. |
1713 | 1715 |
1714 // If the assignment starts a block of assignments to the same object, | 1716 // If the assignment starts a block of assignments to the same object, |
1715 // change to slow case to avoid the quadratic behavior of repeatedly | 1717 // change to slow case to avoid the quadratic behavior of repeatedly |
1716 // adding fast properties. | 1718 // adding fast properties. |
1717 if (expr->starts_initialization_block()) { | 1719 if (expr->starts_initialization_block()) { |
(...skipping 20 matching lines...) Expand all Loading... |
1738 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1740 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1739 | 1741 |
1740 // If the assignment ends an initialization block, revert to fast case. | 1742 // If the assignment ends an initialization block, revert to fast case. |
1741 if (expr->ends_initialization_block()) { | 1743 if (expr->ends_initialization_block()) { |
1742 __ push(r0); // Result of assignment, saved even if not needed. | 1744 __ push(r0); // Result of assignment, saved even if not needed. |
1743 // Receiver is under the result value. | 1745 // Receiver is under the result value. |
1744 __ ldr(ip, MemOperand(sp, kPointerSize)); | 1746 __ ldr(ip, MemOperand(sp, kPointerSize)); |
1745 __ push(ip); | 1747 __ push(ip); |
1746 __ CallRuntime(Runtime::kToFastProperties, 1); | 1748 __ CallRuntime(Runtime::kToFastProperties, 1); |
1747 __ pop(r0); | 1749 __ pop(r0); |
1748 context()->DropAndPlug(1, r0); | 1750 __ Drop(1); |
1749 } else { | |
1750 context()->Plug(r0); | |
1751 } | 1751 } |
| 1752 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 1753 context()->Plug(r0); |
1752 } | 1754 } |
1753 | 1755 |
1754 | 1756 |
1755 void FullCodeGenerator::VisitProperty(Property* expr) { | 1757 void FullCodeGenerator::VisitProperty(Property* expr) { |
1756 Comment cmnt(masm_, "[ Property"); | 1758 Comment cmnt(masm_, "[ Property"); |
1757 Expression* key = expr->key(); | 1759 Expression* key = expr->key(); |
1758 | 1760 |
1759 if (key->IsPropertyName()) { | 1761 if (key->IsPropertyName()) { |
1760 VisitForAccumulatorValue(expr->obj()); | 1762 VisitForAccumulatorValue(expr->obj()); |
1761 EmitNamedPropertyLoad(expr); | 1763 EmitNamedPropertyLoad(expr); |
(...skipping 1431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3193 __ CallStub(&stub); | 3195 __ CallStub(&stub); |
3194 __ bind(&done); | 3196 __ bind(&done); |
3195 | 3197 |
3196 // Store the value returned in r0. | 3198 // Store the value returned in r0. |
3197 switch (assign_type) { | 3199 switch (assign_type) { |
3198 case VARIABLE: | 3200 case VARIABLE: |
3199 if (expr->is_postfix()) { | 3201 if (expr->is_postfix()) { |
3200 { EffectContext context(this); | 3202 { EffectContext context(this); |
3201 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3203 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3202 Token::ASSIGN); | 3204 Token::ASSIGN); |
| 3205 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3206 context.Plug(r0); |
3203 } | 3207 } |
3204 // For all contexts except EffectConstant We have the result on | 3208 // For all contexts except EffectConstant We have the result on |
3205 // top of the stack. | 3209 // top of the stack. |
3206 if (!context()->IsEffect()) { | 3210 if (!context()->IsEffect()) { |
3207 context()->PlugTOS(); | 3211 context()->PlugTOS(); |
3208 } | 3212 } |
3209 } else { | 3213 } else { |
3210 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3214 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3211 Token::ASSIGN); | 3215 Token::ASSIGN); |
| 3216 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3217 context()->Plug(r0); |
3212 } | 3218 } |
3213 break; | 3219 break; |
3214 case NAMED_PROPERTY: { | 3220 case NAMED_PROPERTY: { |
3215 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 3221 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
3216 __ pop(r1); | 3222 __ pop(r1); |
3217 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3223 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
3218 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3224 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3225 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3219 if (expr->is_postfix()) { | 3226 if (expr->is_postfix()) { |
3220 if (!context()->IsEffect()) { | 3227 if (!context()->IsEffect()) { |
3221 context()->PlugTOS(); | 3228 context()->PlugTOS(); |
3222 } | 3229 } |
3223 } else { | 3230 } else { |
3224 context()->Plug(r0); | 3231 context()->Plug(r0); |
3225 } | 3232 } |
3226 break; | 3233 break; |
3227 } | 3234 } |
3228 case KEYED_PROPERTY: { | 3235 case KEYED_PROPERTY: { |
3229 __ pop(r1); // Key. | 3236 __ pop(r1); // Key. |
3230 __ pop(r2); // Receiver. | 3237 __ pop(r2); // Receiver. |
3231 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 3238 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
3232 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3239 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3240 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3233 if (expr->is_postfix()) { | 3241 if (expr->is_postfix()) { |
3234 if (!context()->IsEffect()) { | 3242 if (!context()->IsEffect()) { |
3235 context()->PlugTOS(); | 3243 context()->PlugTOS(); |
3236 } | 3244 } |
3237 } else { | 3245 } else { |
3238 context()->Plug(r0); | 3246 context()->Plug(r0); |
3239 } | 3247 } |
3240 break; | 3248 break; |
3241 } | 3249 } |
3242 } | 3250 } |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3581 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3589 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
3582 __ add(pc, r1, Operand(masm_->CodeObject())); | 3590 __ add(pc, r1, Operand(masm_->CodeObject())); |
3583 } | 3591 } |
3584 | 3592 |
3585 | 3593 |
3586 #undef __ | 3594 #undef __ |
3587 | 3595 |
3588 } } // namespace v8::internal | 3596 } } // namespace v8::internal |
3589 | 3597 |
3590 #endif // V8_TARGET_ARCH_ARM | 3598 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |