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 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); | 832 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); |
833 __ SmiCompare(rax, Smi::FromInt(0)); | 833 __ SmiCompare(rax, Smi::FromInt(0)); |
834 __ j(equal, loop_statement.continue_target()); | 834 __ j(equal, loop_statement.continue_target()); |
835 __ movq(rbx, rax); | 835 __ movq(rbx, rax); |
836 | 836 |
837 // Update the 'each' property or variable from the possibly filtered | 837 // Update the 'each' property or variable from the possibly filtered |
838 // entry in register rbx. | 838 // entry in register rbx. |
839 __ bind(&update_each); | 839 __ bind(&update_each); |
840 __ movq(result_register(), rbx); | 840 __ movq(result_register(), rbx); |
841 // Perform the assignment as if via '='. | 841 // Perform the assignment as if via '='. |
842 EmitAssignment(stmt->each()); | 842 { EffectContext context(this); |
| 843 EmitAssignment(stmt->each(), stmt->AssignmentId()); |
| 844 } |
843 | 845 |
844 // Generate code for the body of the loop. | 846 // Generate code for the body of the loop. |
845 Visit(stmt->body()); | 847 Visit(stmt->body()); |
846 | 848 |
847 // Generate code for going to the next element by incrementing the | 849 // Generate code for going to the next element by incrementing the |
848 // index (smi) stored on top of the stack. | 850 // index (smi) stored on top of the stack. |
849 __ bind(loop_statement.continue_target()); | 851 __ bind(loop_statement.continue_target()); |
850 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); | 852 __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); |
851 | 853 |
852 EmitStackCheck(stmt); | 854 EmitStackCheck(stmt); |
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 __ pop(rdx); | 1516 __ pop(rdx); |
1515 stub.GenerateCall(masm_, rdx, rax); | 1517 stub.GenerateCall(masm_, rdx, rax); |
1516 } else { | 1518 } else { |
1517 __ push(result_register()); | 1519 __ push(result_register()); |
1518 __ CallStub(&stub); | 1520 __ CallStub(&stub); |
1519 } | 1521 } |
1520 context()->Plug(rax); | 1522 context()->Plug(rax); |
1521 } | 1523 } |
1522 | 1524 |
1523 | 1525 |
1524 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1526 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_id) { |
1525 // Invalid left-hand sides are rewritten to have a 'throw | 1527 // Invalid left-hand sides are rewritten to have a 'throw |
1526 // ReferenceError' on the left-hand side. | 1528 // ReferenceError' on the left-hand side. |
1527 if (!expr->IsValidLeftHandSide()) { | 1529 if (!expr->IsValidLeftHandSide()) { |
1528 VisitForEffect(expr); | 1530 VisitForEffect(expr); |
1529 return; | 1531 return; |
1530 } | 1532 } |
1531 | 1533 |
1532 // Left-hand side can only be a property, a global or a (parameter or local) | 1534 // Left-hand side can only be a property, a global or a (parameter or local) |
1533 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1535 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1534 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1536 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
(...skipping 27 matching lines...) Expand all Loading... |
1562 VisitForStackValue(prop->obj()); | 1564 VisitForStackValue(prop->obj()); |
1563 VisitForAccumulatorValue(prop->key()); | 1565 VisitForAccumulatorValue(prop->key()); |
1564 __ movq(rcx, rax); | 1566 __ movq(rcx, rax); |
1565 __ pop(rdx); | 1567 __ pop(rdx); |
1566 __ pop(rax); | 1568 __ pop(rax); |
1567 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1569 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1568 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1570 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1569 break; | 1571 break; |
1570 } | 1572 } |
1571 } | 1573 } |
| 1574 context()->Plug(rax); |
1572 } | 1575 } |
1573 | 1576 |
1574 | 1577 |
1575 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1578 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1576 Token::Value op) { | 1579 Token::Value op) { |
1577 // Left-hand sides that rewrite to explicit property accesses do not reach | 1580 // Left-hand sides that rewrite to explicit property accesses do not reach |
1578 // here. | 1581 // here. |
1579 ASSERT(var != NULL); | 1582 ASSERT(var != NULL); |
1580 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1583 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1581 | 1584 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1634 if (op == Token::INIT_CONST) { | 1637 if (op == Token::INIT_CONST) { |
1635 // The runtime will ignore const redeclaration. | 1638 // The runtime will ignore const redeclaration. |
1636 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1639 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
1637 } else { | 1640 } else { |
1638 __ CallRuntime(Runtime::kStoreContextSlot, 3); | 1641 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
1639 } | 1642 } |
1640 break; | 1643 break; |
1641 } | 1644 } |
1642 __ bind(&done); | 1645 __ bind(&done); |
1643 } | 1646 } |
1644 | |
1645 context()->Plug(rax); | |
1646 } | 1647 } |
1647 | 1648 |
1648 | 1649 |
1649 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1650 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1650 // Assignment to a property, using a named store IC. | 1651 // Assignment to a property, using a named store IC. |
1651 Property* prop = expr->target()->AsProperty(); | 1652 Property* prop = expr->target()->AsProperty(); |
1652 ASSERT(prop != NULL); | 1653 ASSERT(prop != NULL); |
1653 ASSERT(prop->key()->AsLiteral() != NULL); | 1654 ASSERT(prop->key()->AsLiteral() != NULL); |
1654 | 1655 |
1655 // If the assignment starts a block of assignments to the same object, | 1656 // If the assignment starts a block of assignments to the same object, |
(...skipping 16 matching lines...) Expand all Loading... |
1672 } | 1673 } |
1673 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1674 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1674 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1675 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1675 | 1676 |
1676 // If the assignment ends an initialization block, revert to fast case. | 1677 // If the assignment ends an initialization block, revert to fast case. |
1677 if (expr->ends_initialization_block()) { | 1678 if (expr->ends_initialization_block()) { |
1678 __ push(rax); // Result of assignment, saved even if not needed. | 1679 __ push(rax); // Result of assignment, saved even if not needed. |
1679 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1680 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
1680 __ CallRuntime(Runtime::kToFastProperties, 1); | 1681 __ CallRuntime(Runtime::kToFastProperties, 1); |
1681 __ pop(rax); | 1682 __ pop(rax); |
1682 context()->DropAndPlug(1, rax); | 1683 __ Drop(1); |
1683 } else { | |
1684 context()->Plug(rax); | |
1685 } | 1684 } |
| 1685 context()->Plug(rax); |
1686 } | 1686 } |
1687 | 1687 |
1688 | 1688 |
1689 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1689 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1690 // Assignment to a property, using a keyed store IC. | 1690 // Assignment to a property, using a keyed store IC. |
1691 | 1691 |
1692 // If the assignment starts a block of assignments to the same object, | 1692 // If the assignment starts a block of assignments to the same object, |
1693 // change to slow case to avoid the quadratic behavior of repeatedly | 1693 // change to slow case to avoid the quadratic behavior of repeatedly |
1694 // adding fast properties. | 1694 // adding fast properties. |
1695 if (expr->starts_initialization_block()) { | 1695 if (expr->starts_initialization_block()) { |
(...skipping 1424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3120 __ bind(&done); | 3120 __ bind(&done); |
3121 | 3121 |
3122 // Store the value returned in rax. | 3122 // Store the value returned in rax. |
3123 switch (assign_type) { | 3123 switch (assign_type) { |
3124 case VARIABLE: | 3124 case VARIABLE: |
3125 if (expr->is_postfix()) { | 3125 if (expr->is_postfix()) { |
3126 // Perform the assignment as if via '='. | 3126 // Perform the assignment as if via '='. |
3127 { EffectContext context(this); | 3127 { EffectContext context(this); |
3128 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3128 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3129 Token::ASSIGN); | 3129 Token::ASSIGN); |
| 3130 context.Plug(rax); |
3130 } | 3131 } |
3131 // For all contexts except kEffect: We have the result on | 3132 // For all contexts except kEffect: We have the result on |
3132 // top of the stack. | 3133 // top of the stack. |
3133 if (!context()->IsEffect()) { | 3134 if (!context()->IsEffect()) { |
3134 context()->PlugTOS(); | 3135 context()->PlugTOS(); |
3135 } | 3136 } |
3136 } else { | 3137 } else { |
3137 // Perform the assignment as if via '='. | 3138 // Perform the assignment as if via '='. |
3138 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3139 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3139 Token::ASSIGN); | 3140 Token::ASSIGN); |
| 3141 context()->Plug(rax); |
3140 } | 3142 } |
3141 break; | 3143 break; |
3142 case NAMED_PROPERTY: { | 3144 case NAMED_PROPERTY: { |
3143 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 3145 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
3144 __ pop(rdx); | 3146 __ pop(rdx); |
3145 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3147 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
3146 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3148 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3147 if (expr->is_postfix()) { | 3149 if (expr->is_postfix()) { |
3148 if (!context()->IsEffect()) { | 3150 if (!context()->IsEffect()) { |
3149 context()->PlugTOS(); | 3151 context()->PlugTOS(); |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3513 __ ret(0); | 3515 __ ret(0); |
3514 } | 3516 } |
3515 | 3517 |
3516 | 3518 |
3517 #undef __ | 3519 #undef __ |
3518 | 3520 |
3519 | 3521 |
3520 } } // namespace v8::internal | 3522 } } // namespace v8::internal |
3521 | 3523 |
3522 #endif // V8_TARGET_ARCH_X64 | 3524 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |