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