| 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 |